Getting wrong answer on codechef.But my math is right - java

Link of the question-https://www.codechef.com/problems/MATPH
So , I'm stuck on this question for hours and I don't know where I'm wrong.
I have used Sieve of Eratosthenes for finding prime and I saved all prime numbers in hash map.Online judge is giving me wrong answer on test cases.
static void dri(int n) {
long large=0;int r=0,x,count=0,p,count1=0;
x=(int)Math.sqrt(n);
//To understand why I calculated x let's take an example
//let n=530 sqrt(530) is 23 so for all the numbers greater than 23 when
//we square them they will come out to be greater than n
//so now I just have to check the numbers till x because numbers
//greater than x will defiantly fail.I think you get
//what I'm trying to explain
while(r<x) {
r = map.get(++count); // Prime numbers will be fetched from map and stored in r
int exp = (int) (Math.log(n) / Math.log(r));
//To explain this line let n=64 and r=3.Now, exp will be equal to 3
//This result implies that for r=3 the 3^exp is the //maximum(less than n) value which I can calculate by having a prime in a power
if (exp != 1) { //This is just to resolve an error dont mind this line
if (map.containsValue(exp) == false) {
//This line implies that when exp is not prime
//So as I need prime number next lines of code will calculate the nearest prime to exp
count1 = exp;
while (!map.containsValue(--count1)) ;
exp = count1;
}
int temp = (int) Math.pow(r, exp);
if (large < temp)
large = temp;
}
}
System.out.println(large);
}
I

For each testcase, output in a single line containing the largest
beautiful number ≤ N. Print −1 if no such number exists.
I believe that 4 is the smallest beautiful number since 2 is the smallest prime number and 2^2 equals 4. N is just required to ≥ 0. So dri(0), dri(1), dri(2) and dri(3) should all print −1. I tried. They don’t. I would believe that this is the reason for your failure on CodeChef.
I am leaving it to yourself to find out how the mentioned calls to your method behave and what to do about it.
As an aside, what’s the point in keeping your prime numbers in a map? Wouldn’t a list or a sorted set be more suitable?

Related

Java Random.nextInt() behavior

I wrote this simple code just out of curiosity and encountered some behavior of the nextInt() method from the Java Random class that I don't quite understand. Can anyone help me to figure it out?
The program simulates a simple coin flipping. So as far as I understand the probability of the nextInt(101) for numbers less and greater than 49 should be equal.
But as long as I increase the number of iterations, the balance tends to get positive, for example after 100,000 iterations, I didn't get a negative number. Why does this happen?
public static void main(String[] args) {
int balance = 0;
for (int i = 0; i < 100000; i++) {
Random random = new Random();
int result = random.nextInt(101);
if (result > 49) {
balance++;
} else {
balance--;
}
}
System.out.println("Player's balance = " + balance);
}
You call int result = random.nextInt(101) which creates uniformly distributed integers in [0,100], which can take 101 different values. If you check if (result > 49) then you have 51 possible values ([50,100]) and in the else case you have only 50 values ([0,49]). Thus the result is more likely to be in the upper part. To fix it you can do int result = random.nextInt(100).
you are testing 51 possibilities for a positive outcome and only 50 possibilities for a negative outcome.
100-50 = 51 possibilities
0-49 = 50 possibilities.
If you have tried, random.nextInt(99), result will be different, I got minus value many times.
The reason behind this is that random.nextInt() Method.
quoted from the JavaDoc.
The algorithm is slightly tricky. It rejects values that would result
in an uneven distribution (due to the fact that 2^31 is not divisible
by n). The probability of a value being rejected depends on n. The
worst case is n=2^30+1, for which the probability of a reject is 1/2,
and the expected number of iterations before the loop terminates is 2.
Please see here Random.java#nextInt(int)

climbing stairs the int limitation between two solutions

When working on leetcode 70 climbing stairs: You are climbing a stair case. It takes n steps to reach to the top.Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Here is my first solution:
class Solution {
public int fib (int n){
if (n <= 2) return n;
return fib(n-1) + fib(n-2);
}
public int climbStairs(int n) {
return fib (n+1);
}
}
when n <44, it works, but n >=44, it doesn't work.because of this, it leads to the failure in submission in leetcode.
but when use the 2nd solution, shows below
class Solution {
public int climbStairs(int n) {
if (n <= 2) return n;
int[] allWays = new int[n];
allWays[0] = 1;
allWays[1] = 2;
for (int i = 2; i < n; i++){
allWays[i] = allWays[i-1] + allWays[i-2];
}
return allWays[n-1];
}
}
the second solution is accepted by leetcode. however, when n >=46, it gives a negative number.
Can anyone give me some explanation why the first solution fails? what's the difference between the two solutions? Thanks.
Your intuition is correct. The number of ways to reach the top indeed follows the fibonacci sequence.
The first solution computes the fibonacci numbers recursively (fib(n) = fib(n - 1) + fib(n-2)). To compute any value, the function needs to recursively call itself twice. Every function call takes up space in a region of memory called the stack. Whats probably happening is when n is too large, too many recursive calls are happening and the program runs out of space to execute more calls.
The second solution uses Dynamic programming and memoization. This effectively saves space and computation time. If you don't know these topics, I would encourage you to read into them.
You are getting negative values since the 47th Fibonacci number is greater than the maximum value that can be represented by type int. You can try using long or the BigInteger class to represent larger values.
To understand the solution you need to understand the concept of Dynamic Programming and Recursion
In the first solution to calculate the n-th Fibonacci number, your algorithm is
fib(n)= fib(n-1)+fib(n-2)
But the second solution is more optimized
This approach stores values in an array so that you don't have to calculate fib(n) every time.
Example:
fib(5) = fib(4) + fib(3)
= (fib(3) + fib(2)) + (fib(2) + fib(1))
By first solution, you are calculating fib(2) twice for n = 4.
By second solution you are storing fibonacci values in an array
Example:
for n =4,
first you calculate fib(2) = fib(1)+fib(0) = 1
then you calculate f(3) = f(2)+f(1)
We don't have to calculate the fib(2) since it is already stored in the array.
Check this link for more details
for n = 44 no of ways = 1134903170
and for n = 45 no of ways = 1836311903
so for n = 46 number of ways will be n=44 + n=45 i.e 2971215073
sign INTEGER can only store upto 2147483647 i.e. 2^31 - 1
Because of with for n=46 it is showing -ve number

How can I reduce iterations in for loop that takes to much time for execution?

Here, I am finding number of perfect square numbers in given range.
But I am dealing with 'for' loop execution that takes much time for execution.
The index/key traverses from two numbers, lets say A to B, and does some operation in for loop.
The problem arises when there's large difference between A and B (e.g. A = 2 & B = 100000)
Can u suggest how can I reduce or optimize the execution time?
Scanner in = new Scanner(System.in);
int A = in.nextInt();
int B = in.nextInt();
int cnt = 0;
for(int number =A ; number<= B; number++){
int sqrt = (int) Math.sqrt(number);
if(sqrt*sqrt == number) {
cnt++;
}
}
System.out.println(cnt);
Or is it because of Math class operations that takes too much time to execute?
Can you suggest any alternate approach to find the square numbers between given range?
Thanks in advance!
I found an alternate way to find the count of perfect square numbers between given range.
This can be simply achieve by using Math.floor and Math.ceil operations.
Math.floor(Math.sqrt(B)) - Math.ceil(Math.sqrt(A)) + 1
Thanks! :)
Instead of going through each number in the range and figuring out if its a perfect square, I would suggest the below
Find a square root of the start number and find the integer part of it.
Lets say start number is 5. So integer part of the square root will be 2.
Now do the same for the range end number
Lets say end range was 1000, so the integer part of its square root would be 31. Now iterate from 2+1 to 31 and keep printing its square. That would give you the perfect squares between the given range.
Instead of the if(sqrt * sqrt == number) you could also check whether the double returned by Math.srt(number) is a integer. The algorithm would than become as follows:
for(int number =A ; number<= B; number++){
if((Math.sqrt(number) % 1) == 0) {
cnt++;
}
}
Note: Haven't tried the code myself so might not work as I expect.
Regarding the question on how you can improve the performance. The checking on whether the number is perfect could be done in parallel by executing per number a task. The access to the counter has to be synchronized than, (to be on the safe side).

truncated binary logarithm

I have a question about this problem, and any help would be great!
Write a program that takes one integer N as an
argument and prints out its truncated binary logarithm [log2 N]. Hint: [log2 N] = l is the largest integer ` such that
2^l <= N.
I got this much down:
int N = Integer.parseInt(args[0]);
double l = Math.log(N) / Math.log(2);
double a = Math.pow(2, l);
But I can't figure out how to truncate l while keeping 2^l <= N
Thanks
This is what i have now:
int N = Integer.parseInt(args[0]);
int i = 0; // loop control counter
int v = 1; // current power of two
while (Math.pow(2 , i) <= N) {
i = i + 1;
v = 2 * v;
}
System.out.println(Integer.highestOneBit(N));
This prints out the integer that is equal to 2^i which would be less than N. My test still comes out false and i think that is because the question is asking to print the i that is the largest rather than the N. So when i do
Integer.highestOneBit(i)
the correct i does not print out. For example if i do: N = 38 then the highest i should be 5, but instead it prints out 4.
Then i tried this:
int N = Integer.parseInt(args[0]);
int i; // loop control counter
for (i= 0; Math.pow(2 , i) == N; i++) {
}
System.out.println(Integer.highestOneBit(i));
Where if i make N = 2 i should print out to be 1, but instead it is printing out 0.
I've tried a bunch of things on top of that, but cant get what i am doing wrong. Help would be greatly appreciated. Thanks
I believe the answer you're looking for here is based on the underlying notion of how a number is actually stored in a computer, and how that can be used to your advantage in a problem such as this.
Numbers in a computer are stored in binary - a series of ones and zeros where each column represents a power of 2:
(Above image from http://www.mathincomputers.com/binary.html - see for more info on binary)
The zeroth power of 2 is over on the right. So, 01001, for example, represents the decimal value 2^0 + 2^3; 9.
This storage format, interestingly, gives us some additional information about the number. We can see that 2^3 is the highest power of 2 that 9 is made up of. Let's imagine it's the only power of two it contains, by chopping off all the other 1's except the highest. This is a truncation, and results in this:
01000
You'll now notice this value represents 8, or 2^3. Taking it down to basics, lets now look at what log base 2 really represents. It's the number that you raise 2 to the power of to get the thing your finding the log of. log2(8) is 3. Can you see the pattern emerging here?
The position of the highest bit can be used as an approximation to it's log base 2 value.
2^3 is the 3rd bit over in our example, so a truncated approximation to log base 2(9) is 3.
So the truncated binary logarithm of 9 is 3. 2^3 is less than 9; This is where the less than comes from, and the algorithm to find it's value simply involves finding the position of the highest bit that makes up the number.
Some more examples:
12 = 1100. Position of the highest bit = 3 (starting from zero on the right). Therefore the truncated binary logarithm of 12 = 3. 2^3 is <= 12.
38 = 100110. Position of the highest bit = 5. Therefore the truncated binary logarithm of 38 = 5. 2^5 is <= 38.
This level of pushing bits around is known as bitwise operations in Java.
Integer.highestOneBit(n) returns essentially the truncated value. So if n was 9 (1001), highestOneBit(9) returns 8 (1000), which may be of use.
A simple way of finding the position of that highest bit of a number involves doing a bitshift until the value is zero. Something a little like this:
// Input number - 1001:
int n=9;
int position=0;
// Cache the input number - the loop destroys it.
int originalN=n;
while( n!=0 ){
position++; // Also position = position + 1;
n = n>>1; // Shift the bits over one spot (Overwriting n).
// 1001 becomes 0100, then 0010, then 0001, then 0000 on each iteration.
// Hopefully you can then see that n is zero when we've
// pushed all the bits off.
}
// Position is now the point at which n became zero.
// In your case, this is also the value of your truncated binary log.
System.out.println("Binary log of "+originalN+" is "+position);

Project Euler 12: Triangle Number with 500 Divisors

I was reading through the solution to Project Euler Problem 12 on MathBlog and I have some trouble understanding the logic behind the codes. The program uses prime factorisation to find the number of divisors of a triangle number.
private int PrimeFactorisationNoD(int number, int[] primelist) {
int nod = 1;
int exponent;
int remain = number;
for (int i = 0; i < primelist.Length; i++) {
// In case there is a remainder this is a prime factor as well
// The exponent of that factor is 1
if (**primelist[i] * primelist[i] > number**) {
return nod * 2;
}
exponent = 1;
while (remain % primelist[i] == 0) {
exponent++;
remain = remain / primelist[i];
}
nod *= exponent;
//If there is no remainder, return the count
if (remain == 1) {
return nod;
}
}
return nod;
}
I understand most part of the program except for the highlighted portion "primelist[i] * primelist[i] > number". I have trouble understanding the necessity of the this line of code. I will use an example to illustrate my point. Let say I have a number 510 = 2*3*5*17. The highlighted code will only be true when Primelist goes to number 23. But by the time the list goes to number 17, the condition remain == 1 will be true and program would have exited the loop. Would it be better if I change the code to if(remain==primelist[i]) since the loop would end when primelist goes to number 17 instead of 21?
The if condition speeds up the code in certain situations (although it should have "remain" in place of "number"). Once primelist[i] is reached we know that remain is not divisible by primelist[0] through primelist[i-1]. If primelist[i]^2>remain then we can conclude that remain is some prime between primelist[i] and primelist[i]^2-1 (inclusive), as if remain=ab then both a,b would have to be at least primelist[i] so remain would be at least primelist[i]^2, a contradiction. Thus we can stop searching for primes dividing remain.
For an example where this is faster, take number=7. Then the condition is triggered when we reach 3 (as 3^2=9>7), so we do not need to check all the primes up to 7.
First, it should better use remain:
primelist[i] * primelist[i] > remain
It is an optimization, as there can be no divisors between the square root of remain and remain, so you only have the factor remain left.
Also, the variable name exponent is lying, it really contains the exponent plus one. Better initialize it to zero and multiply by exponent + 1.

Categories

Resources