Given number is n digits find 2n digits numbers
that, for example
given number is 3 then 6n numbers are from 100000 -999999
then find count of those numbers that for example
123213
1 + 2 + 3 = 2 + 1 + 3
6 = 6
I found and wrote a program for calculating little numbers, but I need the fastest algorithm to find those numbers. Ideas?
my program :
Scanner scan = new Scanner(System.in);
System.out.println("enter n ");
int say = scan.nextInt();
say *= 2;
int low = (int) Math.pow(10, say - 1);
int max = (int) Math.pow(10, say) - 1;
int counter = 0;
int first = 0;
int last = 0;
for (int i = low; i <= max; i++) {
int number = i;
first = 0;
last = 0;
for (int j = 0; j < say / 2; j++) {
int k = number % 10;
first += k;
number /= 10;
}
for (int j = 0; j < say / 2; j++) {
int k = number % 10;
last += k;
number /= 10;
}
if (first == last) {
// System.out.println(i);
counter++;
}
}
System.out.println(counter);
The numbers are called lucky tickets in Russian (a link to ru.wikipedia.org). Yet, I don't seem to find a good explanation in English besides these slides.
Basically, let us say we have 2n digits, and we want the sum of first n be equal to the sum of last n. We first count c(d,s): the number of sequences of d digits which have sum s. Here, 0 <= d <= n and 0 <= s <= 9n. This can be done by dynamic programming: c(0,0)=1, and for d > 0, c(d,s) = c(d-1,s-0) + c(d-1,s-1) + c(d-1,s-2) + ... + c(d-1,s-9) since we can take any sequence of d-1 digits and write another digit from 0 to 9.
Now, the total number of lucky tickets is the sum for different s of the numbers of lucky tickets where the sum of the first n digits is s and the sum of the last n digits is s. When s is fixed, this number is equal to c(n,s) * c(n,s): there are exactly c(n,s) ways to choose the first half, and equally many to choose the second one.
Thus the answer is sum[s=0..9n] c(n,s)^2.
There are other solutions as well involving advanced maths, but for a programmer's assignment, this would suffice. Once again, I can't find a proper source in English — sorry! Here are a few popular articles in Russian, for what it's worth.
Edit: If you in fact need to account for numbers 100000 to 999999, not 000000 to 999999, a patch would be to calculate sum[s=0..9n] (c'(n,s) * c(n,s)), where c'(n,s) is the same table but calculated with disabled addition of zero digit when adding the first digit.
Related
for(i=0; i<array.length; i++){
sum = 4 * 5;
}
What I'm trying to do is add ((array.length - 1) - i) 0's to the value of sum. For this example assume array length is 3. sum equals 20. So for the first iteration of the loop i want to add ((3 - 1) - 0) 0's to the value of sum, so sum would be 2000. The next iteration would be ((3 - 1) - 1) 0's. so sum would equal 200 and so on. I hope what I am trying to achieve is clear.
So my questions are:
Is it possible to just shift an int to add extra digits? My search thus far suggests it is not.
If not, how can i achieve my desired goal?
Thankyou for reading my question and any help would be greatly apreciated.
You can just multiply it by 10 however many times.
200 * 10 = 2000
etc
So in your case, you'd have to use a for loop until the end of the array and multiply sum every iteration. Be careful though, because the max value of an int is 2^31, so it of surpasses that, it will roll back to 0
You can add n zeroes to the end of a number, sum by multiplying sum by 10 * n.
int sum = 20;
for (int i = 0; i < ary.length; ++i) {
int zeroesToAdd = ary.length - 1 - i
sum *= (zeroesToAdd > 0) ? zeroesToAdd * 10 : 1
}
System.out.println("Sum after loop: " + sum);
for(int i=array.length; i>0; i--){
sum = 20;
for(int j=0; j < (i - 1); j++)
{
sum *= 10;
}
}
Use inner loop to multiply by 10 the number of times i is for that iteration. You would need to reset sum in your outer loop each time.
You will want to check your for-loop condition: i>array.length. Since i starts at 0, this loop will not run unless the array's length is also 0 (an empty array). The correct condition is i < array.length.
This "shift" you want can be achieved by creating a temporary variable inside the loop that is equal to the sum times 10i. In Java's Math library, there is a pow(a,b) function that computes ab. With that in mind, what you want is something like this:
int oldSum = 4 * 5;
for (int i = 0; i < array.length; i++) {
int newSum = oldSum * Math.pow(10,i);
}
Multiply by 10 instead, and use < (not >) like
int sum = 20;
int[] array = { 1, 2, 3 };
for (int i = 0; i < array.length; i++) {
int powSum = sum;
for (int j = array.length - 1; j > i; j--) {
powSum *= 10;
}
System.out.println(powSum);
}
Output is (as requested)
2000
200
20
For array of length = n; you will end up adding (n - 1) + (n - 2) + ... + 2 + 1 + 0 zeros for i = 0, 1, ... n-2, n-1 respectively.
Therefore, number of zeros to append (z) = n * (n-1) / 2
So the answer is sum * (10 ^ z)
[EDIT]
The above can be used to find the answer after N iteration. (I miss read the question)
int n = array.length;
long sum = 20;
long pow = Math.pow(10, n-1); // for i = 0
for (int i = 0; i < n; i++) {
System.out.println(sum*pow);
pow /= 10;
}
This is my code for the Codewars problem (Java) yet I cannot make it work. I'm pretty sure I've made a stupid mistake somewhere because of my lack of experience (coding for 4 months)
public static int zeros(int n) {
int f = 1;
int zerocount = 0;
for(int i = 2 ; i <= n; i++){
f *= i;
}
String factorial = String.valueOf(f);
String split [] = factorial.split("");
for(int i = 0; i < split.length; i++){
String m = split[i];
if(m.equals( "0")){
zerocount ++;
}
else {
zerocount = 0;
}
}
return zerocount;
}
}
In fact, you do not need to calculate the factorial because it will rapidly explode into a huge number that will overflow even a long. What you want to do is count the number of fives and twos by which each number between 2 and n can be divided.
static int powersoffive(int n) {
int p=0;
while (n % 5 == 0) {
p++;
n /= 5;
}
return p;
}
static int countzeros(int n) {
int fives = 0;
for (int i = 1; i <= n; i++)
fives += powersoffive(i);
return fives;
}
Note: Lajos Arpad's solution is superior.
As pointed out by other users your solution will probably not be accepted because of the exploding factorial you are calculating.
About the code you wrote there are two mistakes you have made:
You are calculating the factorial in the wrong way. You should start with i = 2 in the loop
for(int i = 2; i <= n; i++){
f *= i;
}
Also in Java you cannot compare strings using ==. This is not valid
if(m == "0")
You should compare them like this
if(m.equals("0"))
Anyway this is how I would have resolved the problem
public static int zeros(int n) {
int zerocount = 0;
for (int i = 5; n / i > 0; i *= 5) {
zerocount += n / i;
}
return zerocount;
}
A zero in a base-10 representation of a number is a 2*5. In order to determine the number of trailing zeroes you will need to determine how many times can you divide your number with ten, or, in other words, the minimum of the sum of 2 and 5 factors. Due to the fact that 5 is bigger than 2 and we go sequentially, the number of fives will be the number of trailing zeroes.
A naive approach would be to round down n/5, but that will only give you the number of items divisible with 5. However, for example, 25 is divisible by 5 twice. The same can be said about 50. 125 can be divided by 5 three times, no less.
So, the algorithm would look like this:
int items = 0;
int power = 5;
while (power < n) {
items += (int) (n / power);
power *= 5;
}
Here small numbers are in use in relative terms, but it's only a proof of concept.
You do need to use brute force here and you integers will overflow anyway.
With multiplication trailing zero appears only as the result of 2*5.
Now imagine the factorial represented by a product of it's prime factors.
Notice that for every 5 (five) we will always have 2 (two).
So to calculate the number of zeroes we need to calculate the number of fives.
That can be implemented by continuously dividing N by five and totaling results
In Java code that will be something like this:
static int calculate(int n)
{
int result = 0;
while (n > 0 ) {
n /= 5;
result += n;
}
return result;
}
Problem statement: Three digit sum - Find all the numbers between 1 and 999 where the sum of the 1st digit and the 2nd digit is equal to the 3rd digit.
Examples:
123 : 1+2 = 3
246 : 2+4 = 6
Java:
public class AssignmentFive {
public static void main(String[] args) {
int i=1;
int valuetwo;
int n=1;
int sum = 0;
int valuethree;
int valueone = 0;
String Numbers = "";
for (i = 1; i <= 999; i++) {
n = i;
while (n > 1) {
valueone = n % 10;/*To get the ones place digit*/
n = n / 10;
valuetwo = n % 10;/*To get the tens place digit*/
n = n / 10;
valuethree = n;/*To get the hundreds place digit*/
sum = valuethree + valuetwo;/*adding the hundreds place and
tens place*/
}
/*Checking if the ones place digit is equal to the sum and then print
the values in a string format*/
if (sum == valueone) {
Numbers = Numbers + n + " ";
System.out.println(Numbers);
}
}
}
}
I got my result :
1
10
100
1000
10000
100000
1000000
10000000
100000000
1000000000
10000000001
100000000011
1000000000111
10000000001111
100000000011111
1000000000111111
10000000001111111
100000000011111111
1000000000111111111
Process finished with exit code 0
The result is not showing the actual result like it should be which should show values like: 123, 246 (Please refer to the problem statement above.)
Please let me know what seems to be the issue with the code and how to tweak it.
Don't know what you're trying to do with that while loop, or why you are building up a space-separated string of numbers.
Your code should be something like:
for (int n = 1; n <= 999; n++) {
int digit1 = // for you to write code here
int digit2 = // for you to write code here
int digit3 = // for you to write code here
if (digit1 + digit2 == digit3) {
// print n here
}
}
So basically your question is how to calculate the numbers, right?
My first hint for you would be how to get the first, second and third value from a 2 or 3 digit number.
For example for 3 digits you can do int hundretDigit = (n - (n % 100)) % 100. Of course this is really inefficient. But just get code working before optimizing it ;)
Just think about a way to get the "ten-digit" (2nd number). Then you add them and if they equal the third one you write System.out.println(<number>);
EDIT:
For 2 digit numbers I will give you the code:
if(i >= 10 && i <= 99) {
int leftDigit = (i - (i % 10)) / 10;
if(leftDigit == (i % 10)) {
//Left digit equals right digit (for example 33 => 3 = 3
System.out.println(i);
}
}
Try again and edit your source code. If you have more questions I will edit my (this) answer to give you a little bit more help if you need!
for(i=0; i<array.length; i++){
sum = 4 * 5;
}
What I'm trying to do is add ((array.length - 1) - i) 0's to the value of sum. For this example assume array length is 3. sum equals 20. So for the first iteration of the loop i want to add ((3 - 1) - 0) 0's to the value of sum, so sum would be 2000. The next iteration would be ((3 - 1) - 1) 0's. so sum would equal 200 and so on. I hope what I am trying to achieve is clear.
So my questions are:
Is it possible to just shift an int to add extra digits? My search thus far suggests it is not.
If not, how can i achieve my desired goal?
Thankyou for reading my question and any help would be greatly apreciated.
You can just multiply it by 10 however many times.
200 * 10 = 2000
etc
So in your case, you'd have to use a for loop until the end of the array and multiply sum every iteration. Be careful though, because the max value of an int is 2^31, so it of surpasses that, it will roll back to 0
You can add n zeroes to the end of a number, sum by multiplying sum by 10 * n.
int sum = 20;
for (int i = 0; i < ary.length; ++i) {
int zeroesToAdd = ary.length - 1 - i
sum *= (zeroesToAdd > 0) ? zeroesToAdd * 10 : 1
}
System.out.println("Sum after loop: " + sum);
for(int i=array.length; i>0; i--){
sum = 20;
for(int j=0; j < (i - 1); j++)
{
sum *= 10;
}
}
Use inner loop to multiply by 10 the number of times i is for that iteration. You would need to reset sum in your outer loop each time.
You will want to check your for-loop condition: i>array.length. Since i starts at 0, this loop will not run unless the array's length is also 0 (an empty array). The correct condition is i < array.length.
This "shift" you want can be achieved by creating a temporary variable inside the loop that is equal to the sum times 10i. In Java's Math library, there is a pow(a,b) function that computes ab. With that in mind, what you want is something like this:
int oldSum = 4 * 5;
for (int i = 0; i < array.length; i++) {
int newSum = oldSum * Math.pow(10,i);
}
Multiply by 10 instead, and use < (not >) like
int sum = 20;
int[] array = { 1, 2, 3 };
for (int i = 0; i < array.length; i++) {
int powSum = sum;
for (int j = array.length - 1; j > i; j--) {
powSum *= 10;
}
System.out.println(powSum);
}
Output is (as requested)
2000
200
20
For array of length = n; you will end up adding (n - 1) + (n - 2) + ... + 2 + 1 + 0 zeros for i = 0, 1, ... n-2, n-1 respectively.
Therefore, number of zeros to append (z) = n * (n-1) / 2
So the answer is sum * (10 ^ z)
[EDIT]
The above can be used to find the answer after N iteration. (I miss read the question)
int n = array.length;
long sum = 20;
long pow = Math.pow(10, n-1); // for i = 0
for (int i = 0; i < n; i++) {
System.out.println(sum*pow);
pow /= 10;
}
I have a number. This number has many digits. I want to write a function which returns the largest number that consists of some digits of that number. While getting that largest number, the sequence of the digits should not change.
int myFunction(int n, int cat){
...
return max;
}
If n = 38462637 and cat = 3 the function has to return 86637, i.e. if cat = 3 the function is expected to return 5-digit number, as 8 - 3 = 5. The original number has many variations of 5 digits numbers, but the largest possible number is 86637. In this case, the most important requirement is that the digits should not change their place.
Be greedy - select the largest digit that can be leftmost in the answer(if there are several positions where this digit appears, choose its leftmost occurance). A digit may be leftmost if it is not 0 and we have at least n - cat - 1 digits to the right of it.
After that use the same algorithm to create the largest number on the right of the position of this digit that has exactly n - cat - 1 digits. Continue iterating until you have your number composed. Only note that the digits you select after the first iteration may be zero(as they will no longer be leftmost in the resulting number)
EDIT: best solution that uses the algorithm described above - use range minimum query to compute the highest value that is possible for each consecutive digit position. In theory this can be done in constant time per query and linear extra memory using linear precomputation, but the algorithm is so complex and hard to implement that it will only give you improvement for really big values of n. I personally suggest using a segment tree approach that will result in O(n*log(n)) time complexity.
This is probably a bit overcomplicated, but it seems to work:
public static int myFunction(int n, int cat) {
String numString = String.valueOf(n);
int finalLength = numString.length() - cat;
int[] positions = new int[finalLength];
StringBuilder answer = new StringBuilder();
for (int i = 0; i < finalLength; i++) {
for (int j = (i == 0 ? i : positions[i - 1] + 1); j <= numString.length() - finalLength + i; j++) {
if (positions[i] == 0 || numString.charAt(j) > numString.charAt(positions[i]) ) {
positions[i] = j;
}
}
answer.append(numString.charAt(positions[i]));
}
return Integer.parseInt(answer.toString());
}
[EDIT]: A cleaner version without all the String nonsense:
public static int myFunction(int n, int cat) {
List<Integer> digits = new ArrayList<Integer>();
int number = n;
while (number > 0) {
digits.add(number % 10);
number /= 10;
}
int finalLength = digits.size() - cat;
int lastIndex = digits.size();
int answer = 0;
for (int i = 0; i < finalLength; i++) {
int highestDigit = -1;
for (int j = lastIndex - 1; j >= finalLength - i - 1; j--) {
if (digits.get(j) > highestDigit) {
highestDigit = digits.get(j);
lastIndex = j;
}
}
answer = answer * 10 + highestDigit;
}
return answer;
}
If you have access to the code, store the number as a string with a seperator (space, comma, etc) in it, then use the string separator function to put each number (string character) into it's own array location. Parse the string array and make an integer array. Then run a quick sort on the array. When that is done, take the first X number of integers and that is your number.