Interview: Find the whole cubes between range of two Integers - java

I just gave a coding interview on codility
I was asked the to implement the following, but i was not able to finish it in 20 minutes, now I am here to get ideas form this community
Write a function public int whole_cubes_count ( int A,int B ) where it should return whole cubes within the range
For example if A=8 and B=65, all the possible cubes in the range are 2^3 =8 , 3^3 =27 and 4^3=64, so the function should return count 3
I was not able to figure out how to identify a number as whole cube. How do I solve this problem?
A and B can have range from [-20000 to 20000]
This is what I tried
import java.util.Scanner;
class Solution1 {
public int whole_cubes_count ( int A,int B ) {
int count =0;
while(A<=B)
{
double v = Math.pow(A, 1 / 3); // << What goes here?
System.out.println(v);
if (v<=B)
{
count=count+1;
}
A =A +1;
}
return count ;
}
public static void main(String[] args)
{
System.out.println("Enter 1st Number");
Scanner scan = new Scanner(System.in);
int s1 = scan.nextInt();
System.out.println("Enter 2nd Number");
//Scanner scan = new Scanner(System.in);
int s2 = scan.nextInt();
Solution1 n = new Solution1();
System.out.println(n.whole_cubes_count (s1,s2));
}
}

Down and dirty, that's what I say.
If you only have 20 minutes, then they shouldn't expect super-optimized code. So don't even try. Play to the constraints of the system which say only +20,000 to -20,000 as the range. You know the cube values have to be within 27, since 27 * 27 * 27 = 19683.
public int whole_cubes_count(int a, int b) {
int count = 0;
int cube;
for (int x = -27; x <= 27; x++) {
cube = x * x * x;
if ((cube >= a) && (cube <= b))
count++;
}
return count;
}

For the positive cubes:
i = 1
while i^3 < max
++i
Similarly for the negative cubes but with an absolute value in the comparison.
To make this more general, you need to find the value of i where i^3 >= min, in the case that both min and max are positive. A similar solution works if both min and max are negative.

Well, it can be computed with O(1) complexity, we will need to find the largest cube that fits into the range, and the smallest one. All those that are between will obviously also be inside.
def n_cubes(A, B):
a_cr = int(math.ceil(cube_root(A)))
b_cr = int(math.floor(cube_root(B)))
if b_cr >= a_cr:
return b_cr - a_cr + 1
return 0
just make sure your cube_root returns integers for actual cubes. Complete solution as gist https://gist.github.com/tymofij/9035744

int countNoOfCubes(int a, int b) {
int count = 0;
for (int startsCube = (int) Math.ceil(Math.cbrt(a)); Math.pow(
startsCube, 3.0) <= b; startsCube++) {
count++;
}
return count;
}

The solution suggested by #Tim is faster than the one provided by #Erick, especially when A...B range increased.
Let me quote the ground from github here:
"one can notice that x³ > y³ for any x > y. (that is called monotonic function)
therefore for any x that lies in ∛A ≤ x ≤ ∛B, cube would fit: A ≤ x³ ≤ B
So to get number of cubes which lie within A..B, you can simply count number of integers between ∛A and ∛B. And number of integers between two numbers is their difference."
It seems perfectly correct, isn't it? It works for any power, not only for cube.
Here is my port of cube_root method for java:
/*
* make sure your cube_root returns integers for actual cubes
*/
static double cubeRoot(int x) {
//negative number cannot be raised to a fractional power
double res = Math.copySign(Math.pow(Math.abs(x), (1.0d/3)) , x);
long rounded_res = symmetricRound(res);
if (rounded_res * rounded_res * rounded_res == x)
return rounded_res;
else
return res;
}
private static long symmetricRound( double d ) {
return d < 0 ? - Math.round( -d ) : Math.round( d );
}
I am aware of Math.cbrt in java but with Math.pow approach it is easy to generalize the solution for other exponents.

Related

Count Multiples

I have been assigned to write a java program for class that counts multiples. The program takes three integers as input: low, high, x. The program then outputs the number of multiples of x between low and high exclusively.
If the input is: 1, 10, 2
the output would be: 5
My teacher has the proclivity to assign problems we haven't covered in class and I am unsure where to begin. Im not asking for the full code, just how to set up the problem
I am unsure of how to follow my logic thru the program: what I have so far is this
import java.util.Scanner;
public class LabProgram {
public static void main(String[] args) {
Scanner scnr = new Scanner(System.in);
int low, high, x;
int count = 0;
low = scnr.nextInt();
high = scnr.nextInt();
x = scnr.nextInt();
for(int i = low; i <= high; i++){
if(i % x == 0){
count++;
}
if (i % x != 0){
//System.out.println(count);// someone suggested to move this
}
}
System.out.println(count);
}
}
~~~~~~
If I input 1, 10, 2
My output is 01234
Moved the print of count outside of the loop... man I am tired.
FINAL EDIT: This code works, it accomplishes the goal. Thank you to #charisma and everyone else that helped me understand what was going on here. I am new to java but determined to learn more! Thanks all!!!!!
You can input numbers using scanner class similar to the following code from w3schools:
import java.util.Scanner; // Import the Scanner class
class Main {
public static void main(String[] args) {
Scanner myObj = new Scanner(System.in); // Create a Scanner object
System.out.println("Enter username");
String userName = myObj.nextLine(); // Read user input
System.out.println("Username is: " + userName); // Output user input
}
}
low, high and x can be of data type int.
To check which numbers between low and high are multiples of x, you can use a for loop. You can declare a new variable count that can be incremented using count++ every time the for loop finds a multiple. The % operator could be useful to find multiples.
You can output using System.out.println(" " + );
Edit:
% operator requires 2 operands and gives the remainder. So if i % x == 0, it means i is a multiple of x, and we do count++.
The value of i will run through low to high.
for (i = low; i <= high; i++) {
if (i % x == 0) {
count++;
}
}
Once you get to the basic implementation (as explained by Charisma), you'll notice, that it can take a lot of time if the numbers are huge: you have high - low + 1 iterations of the loop. Therefore you can start optimizing, to get a result in constant time:
the first multiple is qLow * x, where qLow is the ceiling of the rational quotient ((double) low) / x,
the last multiple is qHigh * x, where qHigh is the floor of the rational quotient ((double) high) / x,
Java provides a Math.floor() and Math.ceil(), but you can get the same result using integer division and playing with the signs:
final int qLow = -(-low / x);
final int qHigh = high / x;
Now you just have to count the number of integers between qLow and qHigh inclusive.
return qHigh - qLow + 1;
Attention: if x < 0, then you need to use qLow - qHigh, so it is safer to use:
return x > 0 ? qHigh - qLow + 1 : qLow - qHigh + 1;
The case x == 0 should be dealt with at the beginning.
put count++; after the last print statement

Java recursion 1234 to 4321 for example

I have a question how to better tackle this task, I have a version, but I am sure there is a better and shorter way to do this maybe. I need to take any int number(return it as an int without turning it into a String), but never with a 0 at the end (100, 120) but like 1234, or 4132. I need to take this number and using recursion rewrite it the other way around example 1234 to 4321, 4132 to 2314, maybe there is a way this is called, i personally don't know about it.
Here is what I got:
public static int reverse(int r, int n, int k){
if(r==0)
return 0;
else
return + (r%10) * (int)Math.pow(10, (n-k-1))+reverse (r/10, n, k+1)
}
public static void main(String[] args) {
System.out.println(reverse(1234, 4, 0));
}
Working with a String representation of the int may make the code more readable.
Try:
Integer.parseInt(new StringBuilder(r+"").reverse().toString());
Current code doesn't compile. Added a ) to this line:
from if(r==0{ change to if(r==0){
and added a ; in this line return + (r%10) * (int)Math.pow(10, (n-k-1))+reverse (r/10, n, k+1);
Your code after this two changes will look like:
public static int reverse(int r, int n, int k){
if(r==0)
{
return 0;
}else{
return + (r%10) * (int)Math.pow(10, (n-k-1))+reverse (r/10, n, k+1);
}
}
if the number ends with 0, the program will not show any special message to the user, i.e 1230 will return 321. In this case, maybe
maybe print a message ("number must not end with a 0) or throw an exception?
Didn't notice the recursion part.
public static void main(String[] args) {
int i = 589;
System.out.println(reverse(i));
}
public static int reverse(int k){
if(k/10 == 0){return k;}
else return (k%10 * (int)Math.pow(10, (int)Math.log10(k))) + reverse(k /10);
}
Explanation:
k%10 gives you the last digit of an int
(int) (Math.log10(k)) returns
number of Digits in an Integer minus one
public static final int reverse(int number) {
final int lastDigit = number % 10;
final int length = (int) Math.log10(number);
return (number < 10) ? number : (int) (Math.pow(10.0, length) * lastDigit + reverse(number / 10));
}
If the number is lower then 10 it's the number itself. Otherwise it's the last digit multiplied with 10^n where n is the length of the number, so it's now at the position for the first digit.
Then add the result of a reverse of the rest number to it (the number without the last digit).
You take advance of the recursion function itself as it would already work to solve the big problem. You only have to think about the trivial end condition and one single step (which mostly is something you would suggest as the last step)
This is the best way that I could make it using recursion and without conversions.
private static int myReverse(int n, int r) {
if(n == 0)
return r;
int newR = r*10 + n%10;
return myReverse(n/10, newR);
}
What I'm doing here is:
Two parameters: n - the number you want to reverse, r - the reversed number
The recursion stops when n equals 0 because it always dividing it by 10
newR - This variable is unnecessary but it´s better for 'understanding' porposes, first I multiply r by 10 so I can sum the last value o n. For example, reverse 123: along the way if r = 12 and n = 3, first 12*10 = 120, n%10 = 3 then r*10 + n%10 = 123
A 'pleasant' way with only one return statement:
private static int myReverse2(int n, int r) {
return n == 0 ? r : myReverse2(n/10, r*10 + n%10);
}

Position of first significant digit after the decimal point

How can I calculate the position of the first significant digit in a fraction?
Here are a few example inputs with desired output
0.123456 // 1st sign. number position = 1
0.0012345 // ... = 3
0.000012345 // ... = 5
No need for looping. You can simply use the following formula:
Math.ceil(-Math.log10(d))
Example:
public static int firstSignificant(double d) {
return (int) Math.ceil(-Math.log10(d));
}
// Usage
System.out.println(firstSignificant(0.123456)); // 1
System.out.println(firstSignificant(0.0012345)); // 3
System.out.println(firstSignificant(0.000012345)); // 5
A note on some corner cases:
0 has no first significant digit. For this case the formula evaluates to Integer.MAX_VALUE.
You haven't specified what should happen with negative values, but if you want them to behave like positive values you can use Math.abs(d) instead of d in the formula.
You could loop over it count the number of times you need to multiply by ten before it becomes greater or equal to one:
public static int significantDigitNum (double d) {
int cnt = 0;
while (d < 1) {
d *= 10;
++cnt;
}
return cnt;
}
EDIT:
As David Conrad commented, this function will only work for positive numbers. To also support negatives:
public static int significantDigitNum (double d) {
int cnt = 0;
d = Math.abs(d);
while (d < 1) {
d *= 10;
++cnt;
}
return cnt;
}
You can check each character if it is a number between 1-9.
String numberString = "0.000012345";
int position = 1;
for(int i=0;i<numberString.length();i++){
if(String.valueOf(numberString.charAt(i)).matches("[1-9]")){
position=i-1;
break;
}
}

Checking whether a number is in Fibonacci Sequence?

It was asked to find a way to check whether a number is in the Fibonacci Sequence or not.
The constraints are
1≤T≤10^5
1≤N≤10^10
where the T is the number of test cases,
and N is the given number, the Fibonacci candidate to be tested.
I wrote it the following using the fact a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square :-
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for(int i = 0 ; i < n; i++){
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest =(5 * (cand *cand)) + 4;
int bTest = (5 * (cand *cand)) - 4;
int sqrt1 = (int)Math.sqrt(aTest);// Taking square root of aTest, taking into account only the integer part.
int sqrt2 = (int)Math.sqrt(bTest);// Taking square root of bTest, taking into account only the integer part.
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
But its not clearing all the test cases? What bug fixes I can do ?
A much simpler solution is based on the fact that there are only 49 Fibonacci numbers below 10^10.
Precompute them and store them in an array or hash table for existency checks.
The runtime complexity will be O(log N + T):
Set<Long> nums = new HashSet<>();
long a = 1, b = 2;
while (a <= 10000000000L) {
nums.add(a);
long c = a + b;
a = b;
b = c;
}
// then for each query, use nums.contains() to check for Fibonacci-ness
If you want to go down the perfect square route, you might want to use arbitrary-precision arithmetics:
// find ceil(sqrt(n)) in O(log n) steps
BigInteger ceilSqrt(BigInteger n) {
// use binary search to find smallest x with x^2 >= n
BigInteger lo = BigInteger.valueOf(1),
hi = BigInteger.valueOf(n);
while (lo.compareTo(hi) < 0) {
BigInteger mid = lo.add(hi).divide(2);
if (mid.multiply(mid).compareTo(x) >= 0)
hi = mid;
else
lo = mid.add(BigInteger.ONE);
}
return lo;
}
// checks if n is a perfect square
boolean isPerfectSquare(BigInteger n) {
BigInteger x = ceilSqrt(n);
return x.multiply(x).equals(n);
}
Your tests for perfect squares involve floating point calculations. That is liable to give you incorrect answers because floating point calculations typically give you inaccurate results. (Floating point is at best an approximate to Real numbers.)
In this case sqrt(n*n) might give you n - epsilon for some small epsilon and (int) sqrt(n*n) would then be n - 1 instead of the expected n.
Restructure your code so that the tests are performed using integer arithmetic. But note that N < 1010 means that N2 < 1020. That is bigger than a long ... so you will need to use ...
UPDATE
There is more to it than this. First, Math.sqrt(double) is guaranteed to give you a double result that is rounded to the closest double value to the true square root. So you might think we are in the clear (as it were).
But the problem is that N multiplied by N has up to 20 significant digits ... which is more than can be represented when you widen the number to a double in order to make the sqrt call. (A double has 15.95 decimal digits of precision, according to Wikipedia.)
On top of that, the code as written does this:
int cand = sc.nextInt();
int aTest = (5 * (cand * cand)) + 4;
For large values of cand, that is liable to overflow. And it will even overflow if you use long instead of int ... given that the cand values may be up to 10^10. (A long can represent numbers up to +9,223,372,036,854,775,807 ... which is less than 1020.) And then we have to multiply N2 by 5.
In summary, while the code should work for small candidates, for really large ones it could either break when you attempt to read the candidate (as an int) or it could give the wrong answer due to integer overflow (as a long).
Fixing this requires a significant rethink. (Or deeper analysis than I have done to show that the computational hazards don't result in an incorrect answer for any large N in the range of possible inputs.)
According to this link a number is Fibonacci if and only if one or both of (5*n2 + 4) or (5*n2 – 4) is a perfect square so you can basically do this check.
Hope this helps :)
Use binary search and the Fibonacci Q-matrix for a O((log n)^2) solution per test case if you use exponentiation by squaring.
Your solution does not work because it involves rounding floating point square roots of large numbers (potentially large enough not to even fit in a long), which sometimes will not be exact.
The binary search will work like this: find Q^m: if the m-th Fibonacci number is larger than yours, set right = m, if it is equal return true, else set left = m + 1.
As it was correctly said, sqrt could be rounded down. So:
Even if you use long instead of int, it has 18 digits.
even if you use Math.round(), not simply (int) or (long). Notice, your function wouldn't work correctly even on small numbers because of that.
double have 14 digits, long has 18, so you can't work with squares, you need 20 digits.
BigInteger and BigDecimal have no sqrt() function.
So, you have three ways:
write your own sqrt for BigInteger.
check all numbers around the found unprecise double sqrt() for being a real sqrt. That means also working with numbers and their errors simultaneously. (it's horror!)
count all Fibonacci numbers under 10^10 and compare against them.
The last variant is by far the simplest one.
Looks like to me the for-loop doesn't make any sense ?
When you remove the for-loop for me the program works as advertised:
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int cand = sc.nextInt();
if(cand < 0){System.out.println("IsNotFibo"); return; }
int aTest = 5 * cand *cand + 4;
int bTest = 5 * cand *cand - 4;
int sqrt1 = (int)Math.sqrt(aTest);
int sqrt2 = (int)Math.sqrt(bTest);
if((sqrt1 * sqrt1 == aTest)||(sqrt2 * sqrt2 == bTest)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
You only need to test for a given candidate, yes? What is the for loop accomplishing? Could the results of the loop be throwing your testing program off?
Also, there is a missing } in the code. It will not run as posted without adding another } at the end, after which it runs fine for the following input:
10 1 2 3 4 5 6 7 8 9 10
IsFibo
IsFibo
IsFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
IsFibo
IsNotFibo
IsNotFibo
Taking into account all the above suggestions I wrote the following which passed all test cases
import java.io.*;
import java.util.*;
public class Solution {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
long[] fib = new long[52];
Set<Long> fibSet = new HashSet<>(52);
fib[0] = 0L;
fib[1] = 1L;
for(int i = 2; i < 52; i++){
fib[i] = fib[i-1] + fib[i - 2];
fibSet.add(fib[i]);
}
int n = sc.nextInt();
long cand;
for(int i = 0; i < n; i++){
cand = sc.nextLong();
if(cand < 0){System.out.println("IsNotFibo");continue;}
if(fibSet.contains(cand)){
System.out.println("IsFibo");
}else{
System.out.println("IsNotFibo");
}
}
}
}
I wanted to be on the safer side hence I choose 52 as the number of elements in the Fibonacci sequence under consideration.

Algorithm to solve an equation

I have this problem for the course "Algorithm and data structures"
You have a equation x^2+s(x)+200·x=N, where x and N are natural numbers and S(x) is the sum of digits of number x.
On the input we have N and A, B such that A≤B and A, B≤1,000,000,000. You need to check if there is a natural number x in the interval [A, B] that solves the equation. If found you need to return that number, otherwise return -1.
Example Input:
1456
10 80
Output
-1
I managed to solve this problem by using some math and a bit modified version of brute force algorithm. But are there any more effective(algorithm based) ways to solve this problem?
This is my code:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Range {
static int proveri(long N, long A, long B) {
long res = 0;
long start = (long)((-200 + Math.sqrt(4*N + 4))/2);
//System.out.println(start);
for (long i = Math.max(A, start); i <= B; i++) {
res = i * i + S(i) + 200 * i;
if(res == N)
return (int)i;
if(res > N)
return -1;
}
return -1;
}
static int S(long x) {
int sum = 0;
while(x > 0) {
sum += x % 10;
x /= 10;
}
return sum;
}
public static void main(String[] args) throws Exception {
int i,j,k;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
long N = Long.parseLong(br.readLine());
StringTokenizer st = new StringTokenizer(br.readLine());
long A = Long.parseLong(st.nextToken());
long B = Long.parseLong(st.nextToken());
int res = proveri(N, A, B);
System.out.println(res);
br.close();
}
}
Here's a way where you can cut down on the amount of numbers you have to search.
Consider the equation anxn +
an-1xn-1 + ... + a1x + a0 = 0.
The rational root theorem states that if x = p/q is a solution,
then p divides a0 and q divides an
In your case, an is 1 and a0 is equal to S(x)-N. Thus, we know that any solution must divide S(x)-N.
This is where ben75's tip comes in. Since S(x) can't be bigger than 81, we can loop through all of the possible values of S(x), and solve separately. Something like this:
for each possible value of S(x)
loop through every factor x of S(x) - N
check if it is between A and B, if its digits sum to S(x)
and if it is a solution to x*x + 200x + S(x) = N.
if it is, return it.
return -1
There's also a pretty slick way for you to loop through all of the factors of a number, but I'll let you work that one out for yourself since this is for a course. My hint there is to look at the prime factorization of a number.
For the equation x^2+s(x)+200·x=N, consider
x^2 + 200·x + (N - s(x)) = 0
For a solution to a*x^2 + b*x + c = 0 equation with integer solutions, we need to have:
b^2 - 4*a*c >= 0 and must be a perfect square
Hence 200^2 - 4 * (N - s(x)) >=0 and a square or
10000 >= (N - s(x)) and (10,000 - (N - s(x)) must be a square. The square value is therefore less than 10,000 and hence there can be at most 100 values you need to check. With proper values of N it can be much lesser.
Also note that since N < 10,000, s(x) can be at most 36. These should cut down the range quite a bit.

Categories