The challenge is listed here:
The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.
73167176531330624919225119674426574742355349194934
96983520312774506326239578318016984801869478851843
85861560789112949495459501737958331952853208805511
12540698747158523863050715693290963295227443043557
66896648950445244523161731856403098711121722383113
62229893423380308135336276614282806444486645238749
30358907296290491560440772390713810515859307960866
70172427121883998797908792274921901699720888093776
65727333001053367881220235421809751254540594752243
52584907711670556013604839586446706324415722155397
53697817977846174064955149290862569321978468622482
83972241375657056057490261407972968652414535100474
82166370484403199890008895243450658541227588666881
16427171479924442928230863465674813919123162824586
17866458359124566529476545682848912883142607690042
24219022671055626321111109370544217506941658960408
07198403850962455444362981230987879927244284909188
84580156166097919133875499200524063689912560717606
05886116467109405077541002256983155200055935729725
71636269561882670428252483600823257530420752963450
Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?
I have written a code that works with the given 4 digit example, but doesn't work for 13 digits. I suspect there is some type of data overflow, but I am unsure. My super inefficient code is below.
public class Euler8 {
public static void main(String[]args){
String num = "/*number listed above*/";
int n1, n2, n3, n4, n5, n6, n7, n8, n9, n10, n11, n12, n13;
long sum=0, newSum;
for(int n=0; n<=987; n++){
n1=Character.getNumericValue(num.charAt(n));
n2=Character.getNumericValue(num.charAt(n+1));
n3=Character.getNumericValue(num.charAt(n+2));
n4=Character.getNumericValue(num.charAt(n+3));
n5=Character.getNumericValue(num.charAt(n+4));
n6=Character.getNumericValue(num.charAt(n+5));
n7=Character.getNumericValue(num.charAt(n+6));
n8=Character.getNumericValue(num.charAt(n+7));
n9=Character.getNumericValue(num.charAt(n+8));
n10=Character.getNumericValue(num.charAt(n+9));
n11=Character.getNumericValue(num.charAt(n+10));
n12=Character.getNumericValue(num.charAt(n+11));
n13=Character.getNumericValue(num.charAt(n+12));
newSum= (long)(n1*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13);
if(newSum>=sum)
sum=newSum;
}
System.out.println(sum);
}
}
My code outputs this number:
2091059712
Your code makes a cast to long too late: by the time the cast is performed, the multiplication has been completed in 32-bit integers, predictably causing an overflow.
Change the code as follows to fix the problem:
// newSum should be called newProd, because you use multiplication, not addition
newSum= ((long)n1)*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13;
Note that your algorithm is not the most efficient: you could do it 13 times faster if you observe that the product for positions i+1..i+13 can be computed from the product for positions i..i+12 by dividing the value at position i and multiplying by the value at position i+13.
Of course you would have to be careful not to divide by zero. You can work around this by observing that any time you encounter a zero, the next 13 products would all be zero, so you could simply skip them, and move on to the next "train" of non-zeros.
The problem is that n1*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13 overflows because:
they are all int variables, and
an int multiplied by an int gives an int.
The typecase to long is applied to the entire product, and (therefore) happens too late to cause the computations to be done with long arithmetic and avoid the overflow problem.
The simple solution to that particular problem is to declare the n variables as long. It is possible that #dasblinkelights' code (casting n1) is faster ... but you would need to benchmark it to be sure. And there are more significant optimizations than that.
I get the answer as 23514624000 . which is actually correct.
public class LargestProduct {
public static void main(String[]args) {
String s="7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
long k=0,l=13,ans=1,n1,n2,n3,n4,n5,n6,n7,n8,n9,n10,n11,n12,n13;
long Max_Num=0;
String[] result=new String[1000];
result=s.split("");
for(int i=0;i<=987;i++) {
n1=Integer.parseInt(result[i]);
n2=Integer.parseInt(result[i+1]);
n3=Integer.parseInt(result[i+2]);
n4=Integer.parseInt(result[i+3]);
n5=Integer.parseInt(result[i+4]);
n6=Integer.parseInt(result[i+5]);
n7=Integer.parseInt(result[i+6]);
n8=Integer.parseInt(result[i+7]);
n9=Integer.parseInt(result[i+8]);
n10=Integer.parseInt(result[i+9]);
n11=Integer.parseInt(result[i+10]);
n12=Integer.parseInt(result[i+11]);
n13=Integer.parseInt(result[i+12]);
ans=n1*n2*n3*n4*n5*n6*n7*n8*n9*n10*n11*n12*n13;
Max_Num=Math.max(Max_Num, ans);
}
System.out.println(Max_Num);
}
}
Related
I solved a programming question where I had to find the number of 1's in the binary form of the product if 2 numbers A and B. The range of A and B was [0, 10^9] inclusive.
Here is the code I wrote.
public class Solution {
public static void main(String[] args) {
// System.out.println(solution(32329,4746475));
System.out.println(solution(3,4));
}
public static int solution(int A, int B) {
// write your code in Java SE 8
long mul=A*B;
int ans=0;
while(mul>0)
{
if((mul%2)!=0)
{
ans++;
}
mul=mul/2;
}
return ans;
}
}
This worked fine for the input (3,4) but, when I tried (32329,4746475) as input instead the code didn't work and it showed 0 as answer.
I put in a few output statements at different places to debug and found that with this input, the result of multiplication comes out to be -1170032381 (which is wrong) and therefore, the while loop's condition fails. So, I type-casted both A and B like so
long mul=(long)A*(long)B;
And voila it worked. Now, my question is why?
Why did the code work fine for smaller inputs and flop for larger ones and shouldn't 'int to long' be implicit type casting in Java?
(I also tried a few other inputs so not all larger ones give negative as the product but they don't give the correct answer either, smaller ones I've tried till 5-digit A and B give the correct product)
Java has automatic widening from int to long, but that happens at assignment, but the multiplication of an int with another int produces an int, so you would get integer overflow first multiplying 32329 with 4746475, then the widening of the overflowed int result to long.
However, if you first cast at least one of the int to long, then the multiplication is done using long and the result is long, so no integer overflow.
Java int can store from
-2147483648 to 2147483647
32329 X 4746475 =153448790275
as Java does the multiplication before the implicit conversion the result is wrong
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).
All the solutions online I can find use BigInteger but I have to solve this using arrays.
I'm only a beginner and I even took this to my Computer Science club and even couldn't figure it out.
Every time I enter a number greater than 31, the output is always zero.
Also, when I enter a number greater than 12, the output is always incorrect.
E.g. fact(13) returns 1932053504 when it should return 6227020800
Here's what I have so far:
import java.util.Scanner;
class Fact
{
public static void main(String[] args)
{
Scanner kb = new Scanner(System.in);
System.out.println("Enter the number you wish to factorial");
int x = kb.nextInt();
System.out.println(fact(x));
}
public static int fact(int x)
{
int[] a = new int[x];
int product = 1;
for(int i = 0; i < a.length; i++)
{
a[i] = x;
x--;
}
for(int i = 0; i < a.length; i++)
{
product = product * a[i];
}
return product;
}
}
Maximum Values Make Large Numbers Terrible
Sadly, because of the maximum values of integers and longs, you are unable to go any larger than
For Longs:
2^63 - 1
9223372036854775807
9 quintillion 223 quadrillion 372 trillion 36 billion 854 million 775 thousand 807
and For Ints:
2^31 - 1
2147483647
2 billion 147 million 483 thousand 647
(I put the written names in to show the size)
At any point in time during the calculation you go over these, "maximum values," you will overflow the variable causing it to behave differently than you would expect, sometimes causing weird zeros to form.
Even BigIntegers have problems with this although it can go up to numbers way higher than just longs and ints which is why they is used with methods that generate massive numbers like factorials.
You seem to want to avoid using BigInteger and only use primatives so long will be the largest data type that you can use.
Even if you convert everything over to long (except the array iterators of course), you will only be able to calculate the factorial up to 20 accurately. Anything over that would overflow the variable. This is because 21! goes over the "maximum value" for longs.
In short, you would need to either use BigInteger or create your own class to calculate the factorials for numbers greater than 20.
I was trying to solve the simple problem posted on HackerRank.
https://www.hackerrank.com/contests/w16/challenges/sum-of-absolutes
I solved the problem, however its getting time out error to those with input array of size 100000. Could someone help me optimize this code below so it does not timeout.
public static void main(String[] args) {
/* Enter your code here. Read input from STDIN. Print outputto STDOUT. Your class should be named Solution. */
Scanner in = new Scanner(System.in);
int n= in.nextInt();
int q = in.nextInt();
in.nextLine();
int[] a = new int[n+1];
for(int i=1;i<=n;i++)
{
a[i]= in.nextInt();
}
for(int j=0;j<q;j++)
{
int l = in.nextInt();
int r = in.nextInt();
int sum=0;
for(int k=l;k<=r ;k++)
{
sum = Math.abs(sum+a[k]);
}
if(sum%2 == 0)
System.out.println("Even");
else
System.out.println("Odd");
}
}
I think you need to completely rethink your solution: You don;t actually need to work out the summation in order to establish if the result is odd or even.
The observation that adding two even numbers or two odd number gives you an even; and that adding an even and an odd give you an odd for all numbers (positive and negative) should be all you need.
Think about whether there's a shortcut that will give you the same odd/even answer. For example, -8 and 8 are both even while -3 and 3 are both odd. Do you really need to take an absolute value to determine if the sum is even or odd?
---Edit: Another thought or two---
First thought.
Please take a look at Bitwise and Bit Shift Operations. There are bitwise ways to figure out if the number is negative (namely: The high-order bit is 1). And there are bitwise ways to tell if the number is odd (namely: The low-order bit of a positive number is 1 and the low order bit of a negative number is 0).
--- Edit: Second thought---
Could you compress the array by not storing the input numbers, but instead the parity of those numbers? For example, you could use boolean[] isOdd or BitSet isOdd? You could store -7 in position i as isOdd[i] = true; or isOdd.set(i);. (Since BitSet and boolean both initialize to all false, you would not change the boolean or BitSet in position j if position j were even; see BitSet.) Then your answer would consist of counting the odds (or flipping a boolean or not'ing a bit) in the requested set and answering odd if the sum were odd (or false or 0) or even if the sum were even (or true or 1).
Why should you use a BitSet or boolean array? You can pack more information into less memory, making it easier for Java to find the space and leading to fewer page faults should you go over a page boundary.
I'm going to give you two hints. First, always look for needlessly repeated operations (spoiler: how many times do you do Math.abs on each value in the set?). And second, file IO is very expensive. Look for a way to use Scanner more efficiently.
I am trying to printout fibonacci series upto 'N' numbers. All works as per expectation till f(92) but when I am trying to get the value of f(93), values turns out in negative: "-6246583658587674878". How this could be possible? What is the mistake in the logic below?
public long fibo(int x){
long[] arr = new long[x+1];
arr[0]=0;
arr[1]=1;
for (int i=2; i<=x; i++){
arr[i]=arr[i-2]+arr[i-1];
}
return arr[x];
}
f(91) = 4660046610375530309
f(92) = 7540113804746346429
f(93) = -6246583658587674878
Is this because of data type? What else data type I should use for printing fibonacci series upto N numbers? N could be any integer within range [0..10,000,000].
You've encountered an integer overflow:
4660046610375530309 <-- term 91
+7540113804746346429 <-- term 92
====================
12200160415121876738 <-- term 93: the sum of the previous two terms
9223372036854775808 <-- maximum value a long can store
To avoid this, use BigInteger, which can deal with an arbitrary number of digits.
Here's your implementation converted to use BigDecimal:
public String fibo(int x){
BigInteger[] arr = new BigInteger[x+1];
arr[0]=BigInteger.ZERO;
arr[1]=BigInteger.ONE;
for (int i=2; i<=x; i++){
arr[i]=arr[i-2].add(arr[i-1]);
}
return arr[x].toString();u
}
Note that the return type must be String (or BigInteger) because even the modest value of 93 for x produces a result that is too great for any java primitive to represent.
This happened because the long type overflowed. In other words: the number calculated is too big to be represented as a long, and because of the two's complement representation used for integer types, after an overflow occurs the value becomes negative. To have a better idea of what's happening, look at this code:
System.out.println(Long.MAX_VALUE);
=> 9223372036854775807 // maximum long value
System.out.println(Long.MAX_VALUE + 1);
=> -9223372036854775808 // oops, the value overflowed!
The value of fibo(93) is 12200160415121876738, which clearly is greater than the maximum value that fits in a long.
This is the way integers work in a computer program, after all they're limited and can not be infinite. A possible solution would be to use BigInteger to implement the method (instead of long), it's a class for representing arbitrary-precision integers in Java.
As correctly said in above answers, you've experienced overflow, however with below java 8 code snippet you can print series.
Stream.iterate(new BigInteger[] {BigInteger.ZERO, BigInteger.ONE}, t -> new BigInteger[] {t[1], t[0].add(t[1])})
.limit(100)
.map(t -> t[0])
.forEach(System.out::println);