Is there better way of iteration to find the evenly divisible number? - java

I'm trying to solve this problem:
"2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?"
Please, do not tell me the answer, I really want to solve it by myself. All I need is an advice regarding math aspect of the question. The thing is adding one every cycle isn't a good idea because the process is too slow. Or is there a problem with variable type not being long?
I've tried to get number which is evenly divisible of all numbers between (1 and 10), and even (1 and 17), and the algorithm worked well.
int in_num = 1;
int score = 0;
public void calculate() {
while (true) {
score = 0;
for (int x = 1; x < 21; x++) {
if ((in_num%x) == 0) {
score++;
}
}
System.out.println("Number " + in_num + " has " + score );
if (score == 20) {
System.out.println(in_num);
break;
}
in_num++;
}
I expect the specific integer, but I get infinite loop.

Isn't this enough?
Multiply every prime number from 1 to 20 to get the number! Also instead of 2 use 16 and instead of 3 use 9.
Long number = 2 ^ 4 * 3 ^ 2 * 5 * 7 * 11 * 13 * 17 * 19L;
System.out.println(number);
Detailed Answer:
We need to find every prime number less than 20. After that, for each prime number, we must calculate the number to which we can exponentiate the prime number while it stays less than 20.
For example, if we multiply 2 four times with itself it remains below 20 (16). But if we calculate 2 to the fifth, it will be 32 which is greater than 20.
We will do the same for every other prime number. By this calculation the actual answer will be like this:
Long number = 2 ^ 4 * 3 ^ 2 * 5 ^ 1 * 7 ^ 1 * 11 ^ 1 * 13 ^ 1 * 17 ^ 1 * 19L ^ 1;

The lowest common multiple of two numbers x and y is xy/GCD(x,y), where GCD calculates the greatest common divisor.
You can implement GCD easily using Euclid's algorithm or the binary GCD algorithm: https://en.wikipedia.org/wiki/Greatest_common_divisor
The algorithm would be like:
result = 1;
for (x = 20; x > 0; --x)
result *= (x/GCD(x,result));
Of course this works for other numbers as well. If you really don't care about that, then you can just print 232792560

You are getting an infinite loop because of int (in_num) range exceeded its length; replace type int to Long (something bigger than int) you will not get any infinite loop and you will get your output.

Related

Why is this solution to Reverse Integer (Leet Code) O((log10(n))?

The problem in question asks to reverse a 32-bit signed integer. Here's the given solution in Java:
public int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > Integer.MAX_VALUE/10 || (rev == Integer.MAX_VALUE / 10 && pop > 7)) return 0;
if (rev < Integer.MIN_VALUE/10 || (rev == Integer.MIN_VALUE / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
}
​According to the solution's explanation, it's time complexity is O(log10(n)) because there are roughly log10(x) digits in x. Intuitively, there seems to be n-1 iterations of the while loop, where n is the number of digits. (I.E: a 7 digit number requires 6 iterations) However, the solution and given complexity implies that the n is the integer itself and not the number of digits. Can anyone help me gain an intuitive understanding of why the above solution is log10(n) ?
If x is an integer, then floor(log10(x)) + 1 is equal to the number of digits in x.
Let log(10)x = some number y. Then 10^y = x.
For example,
log(10) 10 = 1
log(10) 100 = 2
log(10) 1000 = 3
...
When x is not a perfect power of 10:
floor( log(213) ) = 2
Let me know if this doesn't answer your question.
Let's say the x = 123.
int rev = 0;
rev = rev * 10 + x % 10; // rev = 3, 1st iteration.
x = x/10; // x = 12
rev = rev * 10 + x % 10; // rev = 3 * 10 + 2 = 32, 2nd iteration
x = x/10; // x = 1
rev = rev * 10 + x % 10; // rev = 32 * 10 + 1 = 321, 3rd iteration.
x = 0 so the loop terminates after 3 iterations for 3 digits.
The conditionals within the loop check to see if the reversed values would exceed what a 32 bit number could hold.
So it is log10(n) exactly for the reason you stated in your question. The log of a number n to a given base is the exponent required to raise the base back to the number n. And the exponent is an approximation of the number of digits in the number.
Based on your comment, it could also have been stated that "For any number n, where m is the the number of digits in n, the time complexity is O(m)."
The given reverse algorithm requires in the worst case log_10(x) iterations. In other words, if the given input x consists of k decimal digits, it requires k iterations. But stating that this algorithm is O(log_10(x)) is misleading. This is not logarithmic algorithm. If the input size is not intuitive (for example, testing whether given integer is a prime), we need to rigorously apply the correct definition of input size. In Big O analysis, the input size is defined as the number of characters it takes to write the input. Since we normally encode integers in binary digits, the input size of this algorithm n is approximately log_2 x. Therefore, x is roughly 2^n. The worst case complexity W(x) = log_10 (x) = log_10(2^n) = n log_10(2). Therefore, the big O of reverse algorithm is O(n).

Count number of pairs of two numbers less than or equal to N such that Sum of the digits of numbers of pair is Prime

Given a number N, count all pairs (X,Y) such that sum of to the digits of X and Y is prime. Conditions are as follows.
1 <= N <= 10^50
0 <= X,Y <= N
(X,Y) and (Y,X) are same pair.
I could think of brute force approach. In which I need to put two loops ranging from 1 to N and compute sum of digits for each x and y pair and check whether its prime or not. But its not an optimal solution as N has range 10^50.
I've been taking a stab at this -- it took me a couple of tries just to understand the problem. I want to write up what I learned before I give up and move onto something easier!
First, my rework of #shiva's solution that produces correct output faster:
import sys
from functools import lru_cache
def sum_of_digits(number):
summation = 0
while number > 0:
summation += number % 10
number //= 10
return summation
#lru_cache()
def is_prime(number):
if number < 2:
return False
if number % 2 == 0:
return number == 2
divisor = 3
while divisor * divisor <= number:
if number % divisor == 0:
return False
divisor += 2
return True
maximum = int(sys.argv[1])
count = 0
for i in range(maximum + 1):
sum_i = sum_of_digits(i)
for j in range(i, maximum + 1):
if is_prime(sum_i + sum_of_digits(j)):
count += 1
print(count)
I use this as a benchmark below for both speed and accuracy.
The number of primes needed is trivial, even for 10^50, and can/should be computed ahead. The number of digit sums that are generated is also relatively small and can be stored/hashed. My solution hashes all the possible digit sums from 0 to 10^N, storing the number of times each sum is generated as the value. It then does a pair of nested loops over the digit sums (keys) and if the sum of those sums is a prime, it adds to the count the product of the number of ways each sum can be computed (i.e. multiplies the values).
import sys
from math import ceil
from collections import defaultdict
VERBOSE = False
def sum_of_digits(number):
summation = 0
while number:
summation += number % 10
number //= 10
return summation
def sieve_primes(n):
sieve = [False, False] + [True] * (n - 1)
divisor = 2
while divisor * divisor <= n:
if sieve[divisor]:
for i in range(divisor * divisor, n + 1, divisor):
sieve[i] = False
divisor += 1
return [number for number in range(2, n + 1) if sieve[number]]
power = int(sys.argv[1]) # testing up to 10 ** power
maximum_sum_of_digits = 18 * power
primes_subset = sieve_primes(maximum_sum_of_digits)
sums_of_digits = defaultdict(int)
for i in range(10 ** power + 1):
sums_of_digits[sum_of_digits(i)] += 1
if VERBOSE:
print('maximum sum of digits:', maximum_sum_of_digits)
print('maximum prime:', primes_subset[-1])
print('number of primes:', len(primes_subset))
print('digit sums cached', len(sums_of_digits))
primes_subset = set(primes_subset)
count = 0
for i in sums_of_digits:
sum_i = sums_of_digits[i]
for j in sums_of_digits:
if i + j in primes_subset:
count += sum_i * sums_of_digits[j]
print(ceil((count + 2) / 2)) # hack to help adjust between duples and no duples count; sigh
(Turn on the VERBOSE flag to see more information about the problem.)
Unfortunately, this counts both (X, Y) and (Y, X), contrary to the problem specification, so there's an approximate correction hack at the end of the code to adjust for this. (Please suggest an exact correction!) I call my result an approximation but it usually only undercounts by 1 or 2. Unlike #shiva's code, this one takes a power of 10 as its argument since it's goal is to see how close to 10^50 it can get.
Would be glad to see a result for N=10^50 (or at least 10^8) – MBo
#Shiva reworked My Attempt
exact secs approx secs
10^1 24 0.03 24 0.03
10^2 1544 0.04 1544 0.04
10^3 125030 0.49 125029 0.04
10^4 12396120 51.98 12396119 0.05
10^5 1186605815 6223.28 1186605813 0.14
10^6 113305753201 1.15
10^7 11465095351914 12.36
10^8 1120740901676507 137.37
10^9 105887235290733264 1626.87
#shiva's revamped solution is useless above 10^4 and mine bogs down above 10^8. So getting to 10^50 is going to take a different approach. I hope some of this code and analysis will help towards that effort.
Try this python code and debug:
def sumofdigits(num):
sum=0
while num>0:
sum+=num%10
num=num//10
return sum
def isprime(num):
if num==0:
return False
i = 2
while i<num:
if num%i==0:
return False
i+=1
return True
number = int(input("Enter number:"))
for i in range(0,number+1):
for j in range(i,number+1):
if isprime(sumofdigits(i)+sumofdigits(j)):
print(i,j);
Sample output:

Trying to find the number of x's that satisfies n + x = n ^ x fails with timeout

I'm trying to solve the following problem from the section Bit Manipulation at the Hacker Rank site using new features of Java 8 such as Streams.
The problem description:
Given an integer, n, find each x such that:
0 <= x <= n
n + x = n ^ x
where ^ denotes the bitwise XOR operator. Then print an integer denoting the total number of x's satisfying the criteria above.
Constraints
0 <= n <= 1015
Sample Input: 5
Sample Output: 2
Explanation:
For n = 5, the x values 0 and 2 satisfy the conditions:
5 + 0 = 5 ^ 0 = 5
5 + 2 = 5 ^ 2 = 7
Thus, we print 2 as our answer.
Sample Input: 10
Sample Output: 4
Explanation:
For n = 10, the x values 0, 1, 4, and 5 satisfy the conditions:
10 + 0 = 10 ^ 0 = 10
10 + 1 = 10 ^ 1 = 11
10 + 4 = 10 ^ 4 = 14
10 + 5 = 10 ^ 5 = 15
Thus, we print 4 as our answer.
My code is as follows:
public class SumVsXor
{
public static void main(String[] args)
{
Scanner in = new Scanner(System.in);
long n = in.nextLong();
long count = LongStream.rangeClosed(0, n)
.filter(k -> k + n == (k ^ n))
.count();
System.out.println(count);
}
}
The problem is this code doesn't pass all the test cases.
It works for small values of n, but for large values such as 1000000000000000 it fails due to timeout.
I wonder whether LongStream can't handle Streams with that many elements.
The problem with your code is that it is very inefficient. For the case of n==1000000000000000, your Stream pipeline is performing 1,000,000,000,000,000 addition and XOR operations, which takes a long time. Testing for each number between 0 and n whether n + x == n ^ x would take a long time even if you use a for loop instead of Streams.
Instead of checking all the numbers between 0 and n, you should try to figure out a better way to calculate the required total number of x's. That fact that this problem appears under a "Bit Manipulation" section should give you a hint
to look into the bits of numbers that satisfy n + x == n ^ x.
Let's consider the case of n==1000000000000000. The binary representation of that large number is
0000000000000011100011010111111010100100110001101000000000000000
=== == = ====== = = = == == =
--- - - - - -- -- --- - ---------------
~~~~~~~~~~~~~~
In order for n + x to be equal to n ^ x, x must have a 0 value in all the bits corresponding with the 1 bits of n (marked with = above), and either 0 or 1 value in the bits corresponding with the 0 bits of n (marked with - above). This doesn't include the leading 0s (marked with ~ above), since x must be <= n, so any leading 0s in n must also have a 0 value in x.
This means that the total number of x's for which n + x == n ^ x is 2the number of 0s in n, not including leading 0s.
In the case of n = 1000000000000000, there are 30 such 0 bits, so the total number of x's that satisfy the requirement is 230.
Here's one way to compute the total number of x's :
long n = 1000000000000000L;
int zeroBitsCount = 0;
while (n > 0) {
if (n % 2 == 0) {
zeroBitsCount++; // counts the number of non-leading 0 bits
}
n = n >> 1; // divide n by 2 in order to examine the next bit in the next iteration
}
long total = 1L << zeroBitsCount; // the total is 2^(the 0 bits count)
I came to the same result, but via a different explanation, so thought I might post it here.
Eran's answer got to the same conclusion that I did : to modify the zeroes in the binary representation of the initial number - that is pretty straightforward.
Let's suppose our number is
101010100
so it has 5 zeroes.
you need all the possible combinations of:
a single zero
two zeroes
three zeroes
four zeroes
five zeroes
that is actually :
comb(1,5) + comb(2,5) + comb(3,5) + comb(4,5) + comb (5,5)
that is a well known formula being equal to:
pow(2,n) // where n is five in our case
from there the solution is obvious...
This is a simple question if you know little bit about XOR. I don't know much about java. But I can explain in python.
1.First convert the number to binary.
2.Count the number of zeros in that binary number.
3.print 2 ^ (number of zeros) and that's it.
Here is my python code.
n = int(input())
sum = 0
if n!=0:
n=str(bin(n))
for i in range(len(n)):
if n[i]=='0':
sum = sum + 1
print(2**(sum-1))
else: print(1)
The reason to decrement the sum by 1 is, in python it convert the number to the binary as this format. e.g: 0b'10101.
public static void main (String[] args) {
Scanner in = new Scanner (System.in);
long n = in.nextLong();
long count = 1L << (64-Long.bitCount(n)-Long.numberOfLeadingZeros(n));
System.out.println(count);
}

Given a stock of integers 0-9, what is the last number I can write before I run out of some integer?

As the title says, given a stock of integers 0-9, what is the last number I can write before I run out of some integer?
So if I'm given a stock of, say 10 for every number from 0 to 9, what is the last number I can write before I run out of some number. For example, with a stock of 2 I can write numbers 1 ... 10:
1 2 3 4 5 6 7 8 9 10
at this point my stock for ones is 0, and I cannot write 11.
Also note that if I was given a stock of 3, I could still write only numbers 1 ... 10, because 11 would cost me 2 ones, which would leave my stock for ones at -1.
What I have come up so far:
public class Numbers {
public static int numbers(int stock) {
int[] t = new int[10];
for (int k = 1; ; k++) {
int x = k;
while (x > 0) {
if (t[x % 10] == stock) return k-1;
t[x % 10]++;
x /= 10;
}
}
}
public static void main(String[] args) {
System.out.println(numbers(4));
}
}
With this I can get the correct answer for fairly big stock sizes. With a stock size of 10^6 the code completes in ~2 seconds, and with a stock of 10^7 numbers it takes a whole 27 seconds. This is not good enough, since I'm looking for a solution that can handle stock sizes of as big as 10^16, so I probably need a O(log(n)) solution.
This is a homework like assignment, so I didn't come here without wrestling with this pickle for quite some time. I have failed to come up with anything similiar by googling, and wolfram alpha doesn't recognize any kind of pattern this gives.
What I have concluded so far is that ones will allways run out first. I have no proof, but it is so.
Can anyone come up with any piece of advice? Thanks a lot.
EDIT:
I have come up with and implemented an efficient way of finding the cost of numbers 1...n thanks to btilly's pointers (see his post and comments below. also marked as a solution). I will elaborate this further after I have implemented the binary search for finding the last number you can write with the given stock later today.
EDIT 2: The Solution
I had completely forgotten about this post, so my apologies for not editing in my solution earlier. I won't copy the actual implementation, though.
My code for finding the cost of a number does the following:
First, let us choose a number, e.g. 9999. Now we will get the cost by summing the cost of each tens of digits like so:
9 9 9 9
^ ^ ^ ^
^ ^ ^ roof(9999 / 10^1) * 10^0 = 1000
^ ^ roof(9999 / 10^2) * 10^1 = 1000
^ roof(9999 / 10^3) * 10^2 = 1000
roof(9999 / 10^4) * 10^3 = 1000
Thus the cost for 9999 is 4000.
the same for 256:
2 5 6
^ ^ ^
^ ^ roof(256 / 10^1) * 10^0 = 26
^ roof(256 / 10^2) * 10^1 = 30
roof(256 / 10^3) * 10^2 = 100
Thus the cost for 256 is 156.
Implementing with this idea would make the program work only with numbers that have no digits 1 or 0, which is why further logic is needed. Let's call the method explained above C(n, d), where n is the number for which we are getting the cost for, and d is the d'th digit from n that we are currently working with. Let's also define a method D(n, d) that will return the d'th digit from n. Then we will apply the following logic:
sum = C(n, d)
if D(n, d) is 1:
for each k < d, k >= 0 :
sum -= ( 9 - D(n, k) ) * 10^(k-1);
else if D(n, d) is 0:
sum -= 10^(d-1)
With this the program will calculate the correct cost for a number efficiently. After this we simply apply a binary search for finding the number with the correct cost.
Step 1. Write an efficient function to calculate how much stock needs to be used to write all of the numbers up to N. (Hint: calculate everything that was used to write out the numbers in the last digit with a formula, and then use recursion to calculate everything that was used in the other digits.)
Step 2. Do a binary search to find the last number you can write with your amount of stock.
We can calculate the answer directly. A recursive formula can determine how much stock is needed to get from 1 to numbers that are powers of ten minus 1:
f(n, power, target){
if (power == target)
return 10 * n + power;
else
return f(10 * n + power, power * 10, target);
}
f(0,1,1) = 1 // a stock of 1 is needed for the numbers from 1 to 9
f(0,1,10) = 20 // a stock of 20 is needed for the numbers from 1 to 99
f(0,1,100) = 300 // a stock of 300 is needed for the numbers from 1 to 999
f(0,1,1000) = 4000 // a stock of 4000 is needed for the numbers from 1 to 9999
Where it gets complicated is accounting for the extra 1's needed when our calculation lands after the first multiple of any of the above coefficients; for example, on the second multiple of 10 (11-19) we need an extra 1 for each number.
JavaScript code:
function f(stock){
var cs = [0];
var p = 1;
function makeCoefficients(n,i){
n = 10*n + p;
if (n > stock){
return;
} else {
cs.push(n);
p *= 10;
makeCoefficients(n,i*10);
}
}
makeCoefficients(0,1);
var result = -1;
var numSndMul = 0;
var c;
while (stock > 0){
if (cs.length == 0){
return result;
}
c = cs.pop();
var mul = c + p * numSndMul;
if (stock >= mul){
stock -= mul;
result += p;
numSndMul++;
if (stock == 0){
return result;
}
}
var sndMul = c + p * numSndMul;
if (stock >= sndMul){
stock -= sndMul;
result += p;
numSndMul--;
if (stock == 0){
return result;
}
var numMul = Math.floor(stock / mul);
stock -= numMul * mul;
result += numMul * p;
}
p = Math.floor(p/10);
}
return result;
}
Output:
console.log(f(600));
1180
console.log(f(17654321));
16031415
console.log(f(2147483647));
1633388154

Can someone explain the following method that is used to find the length of the repeating cycle or period of a repeating decimal?

After reading information off the Wikipedia page for repeating decimals, I have found a way to find the number of digits in the repeating part of a decimal.
For example,
1/3 = 0.333333333333333333333333333333... so the result is 1 digit.
1/7 = 0.142857142857142857142857142857... so the result is 6 digits.
However, my method (in Java) did not work for 1/6 which should yield 1 because:
1/6 = 0.1666... so the result is 1 digit despite the non-repeating part of the decimal.
I have found a solution that works (credit to Nayuki Minase).
private static int getCycleLength(int n)
{
Map<Integer,Integer> stateToIter = new HashMap<Integer,Integer>();
int state = 1;
int iter = 0;
while (!stateToIter.containsKey(state))
{
stateToIter.put(state, iter);
state = state * 10 % n;
iter++;
}
System.out.println(iter + " - " + stateToIter.get(state));
return iter - stateToIter.get(state);
}
Can someone please explain to me how this algorithm works? Thank you.
Nayuki here. The code is from Project Euler p026.java. Let me explain what's going on.
The main idea is that we simulate long division and detect when the remainder starts repeating. Let's illustrate with an example of computing 1/7.
0.142857...
-------------
7 | 1.000000000
7
---
30
28
--
20
14
--
60
56
--
40
35
--
50
49
--
10
...
To perform long division, we perform these steps:
Set divisor = 7. Set dividend = 1. (We are computing 1/7.)
----
7 | 1
How many times does the divisor go into the dividend? Let this be k. Append this digit to the quotient.
0
---
7 | 1
Subtract k × divisor from the dividend. This is the remainder.
0
---
7 | 1
-0
--
1
Shift in a new digit on the right side. In our case, it's an infinite decimal of zeros. This is equivalent to multiplying the dividend by 10.
0
---
7 | 1.0
-0
--
10
Go to step 2 and repeat infinitely.
0.1
-----
7 | 1.0
-0
--
10
-7
--
3
...
We update the dividend in every iteration of long division. If the dividend takes on a value that it previously did, then it will generate the same decimal digits.
Now, in code:
// Step 1
int divisor = 7;
int dividend = 1;
while (true) {
// Step 2
int k = dividend / divisor; // Floor
// Step 3
dividend -= k * divisor;
// Step 4
dividend *= 10;
}
With a bit of math, steps 2 and 3 can be combined as dividend %= divisor;. Furthermore, this can be combined with step 4 to get dividend = dividend % divisor * 10;.
The map keeps track of the first time each dividend state was seen. In our example:
The remainder 1 was seen at iteration 0.
The remainder 3 was seen at iteration 1.
The remainder 2 was seen at iteration 2.
The remainder 6 was seen at iteration 3.
The remainder 4 was seen at iteration 4.
The remainder 5 was seen at iteration 5.
The remainder 1 was seen at iteration 6.
The state at iteration 6 is the same as the state at iteration 0. Furthermore, this is the shortest cycle. Hence, the cycle length is 6 − 0 = 6.
So in this algorithm this line is the key.
while(!stateToIter.containsKey(state))
It is breaking the program when it found a repetitive state. Now finding a repetitive state means we are detecting a repeating cycle. Lets go through the problem, say we have to find out for 6.
The way we do 1 / 6 is
Problem :6 | 1 | Result = ?
Step 1:
Add 0. in the result and multiply 1 with 10
6 | 10 | 0.
Iteration
Step 2:
Do the division
6 | 10 | 0.1
6
-----
4 [Mod]
Iteration = 0
Step 3:
Multiply mod with 10 and carry on
6 | 10 | 0.16
6
-----
40
36
-----
04 [Mod]
Iteration = 1
Now we find a repeating mod so now matter how far we go we always get 4 as mod and our result will be 0.166666.. and so on so our repeating cycle will be 1 which is our iteration.
When conventing to decimal you progressively multiply the value you have by 10 until you either have 0 (no more to write) or give up (you have reached the limit of your precision)
Once you have the same value you are working on again, you will repeat the same digits from that point. What the method does is find when you get a repeating values and computes how long it have been since you first saw it (the length of the repeating cycle)
BTW Another solution to this problem which avoids using a Map. Any repeating sequence must be a multiple of 1/9 or 1/99 or 1/999 or 1/9999 etc. This finds how many nines is required for the divisor to be a factor. This is the point at which it repeats.
public static void main(String... args) throws IOException {
for (int i = 3; i < 100; i++) {
System.out.println("i: " + i + " f: " + 1.0 / i + " repeat: " + getRepeatingCount(i));
}
}
public static final BigInteger TEN_TO_19 = BigInteger.TEN.pow(19);
public static int getRepeatingCount(int divisor) {
if (divisor <= 0) throw new IllegalArgumentException();
while (divisor % 2 == 0) divisor /= 2;
while (divisor % 5 == 0) divisor /= 5;
int count = 1;
if (divisor == 1) return 0;
for (long l = 10; l > 0; l *= 10) {
long nines = l - 1;
if (nines % divisor == 0)
return count;
count++;
}
for(BigInteger bi = TEN_TO_19; ; bi = bi.multiply(BigInteger.TEN)) {
BigInteger nines = bi.subtract(BigInteger.ONE);
if (nines.mod(BigInteger.valueOf(divisor)).equals(BigInteger.ZERO))
return count;
count++;
}
}

Categories

Resources