Code works extremely slowly and does not print output - java

I'm working on Project Euler problem #2:
Each new term in the Fibonacci sequence is generated
by adding the previous two terms. By
starting with 1 and 2, the first 10 terms will be:
1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
Find the sum of all the even-valued terms in the sequence which do not exceed four million.
My code:
public class Two {
public static void main(String[] args) {
Two obj = new Two();
int sum = 0, i = 1;
while (obj.fibonacci(i) < 4000001) {
if (obj.fibonacci(i) % 2 == 0) {
sum += obj.fibonacci(i);
i++;
}
}
System.out.println(sum);
}
public int fibonacci(int n) {
if (n == 0) {
return -1;
}
if (n == 1) {
return 1;
}
if (n == 2) {
return 3;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
}
Please help me that what is wrong with this code that when I run it. It doesn't show the output on the console and the total time will be over than 5 minutes
Thanks

You're stuck in an infinite loop there as you're only increasing i when its mod 2 is equal to 0. You need to move your i++ lower.
while (obj.fibonacci(i) <= 4000000) {
if (obj.fibonacci(i) % 2 == 0) {
sum += obj.fibonacci(i);
}
i++;
}
As other comments have metioned, this isn't the best way to solve the fibonacci problem, but it solves your error/problem. You should walk this through a debugger if you don't see why and you'll notice you use a lot of recursive calls which have already been solved. Since you're calling it numerous times in the code, (in the while statement and in the if statement) you've increased your processing time.
Here is a sample of your fibonacci calls, notice how you call the fibonacci method on the same number multiple times:
1
2
3
2
1
4
3
2
1
2
5

As mentioned, the i++ needs to be moved outside the check for eveness or you'll be stuck in a loop.
But you have a slightly bigger problem. The fibonacci sequence starts with
...1, 2, 3, ...
where instead you have ...1, 3, ... which means you get incorrect results. You should have:
// ...
if (n == 2) {
return 2;
// ...

Although you solution might work, it is quite expensive as it recalculates results already obtained.
Using recursion in this case, to have the value of fibonacci(4), you recursively add the values of fibonacci(3) and fibonacci(2), which you already calculated previously.
Try with storing your values in a list instead of recomputing all the time:
List<Long> fibonacci = new ArrayList<Long>();
// First terms
fibonacci.add(-1L); // 0 is dummy, sequence starts at 1
fibonacci.add(1L);
fibonacci.add(2L);
for (int i = 3; fibonacci.get(i - 1) + fibonacci.get(i - 2) < 4000001; i++) {
long u = fibonacci.get(i - 1) + fibonacci.get(i - 2);
fibonacci.add(i, u);
}
Using this technique, you can compute the Fibonacci sequence up to 4000000 in less than 2 seconds (as I tried on my computer).
Then, just add some code to compute the sum inside the loop :-)

One of your problems is that you're excessively using recursion. You should try to store results to avoid to recalculate everything every time.

There's no reason to store the whole sequence of Fibonacci numbers in this case. You can simply "walk" along the sequence with a few local variables, summing as you go.
int fib2 = 0, fib1 = 1, fib0 = fib1 + fib2;
int sum = 0;
while (fib0 <= N)
{
if (fib0 % 2 == 0) sum += fib0;
fib2 = fib1;
fib1 = fib0;
fib0 = fib1 + fib2;
}

An improvement on #Blastfurnace's solution is to note that every third value is even.
public static void main(String[] args) {
long sum = 0;
int runs = 30000;
for (int i=0;i< runs;i++) {
sum = sumEvenFib();
}
long start = System.nanoTime();
for (int i=0;i< runs;i++) {
sum = sumEvenFib();
}
long time = System.nanoTime() - start;
System.out.println(sum+" took "+time/runs+" ns avg");
}
private static long sumEvenFib() {
int sum = 0;
for(int f1 = 1, f2 = 2;f2 < 4000001;) {
sum += f2;
int f3 = f1 + f2;
f1 = f3 + f2;
f2 = f1 + f3;
}
return sum;
}
On my old labtop this takes about 40 ns. or 0.000000040 seconds.

I think you can improve fibonacci next way:
def fib(x)
if(x==0 or x==1) then
return x;
end
a,b = 0,1
(x-1).times{ a,b = b,a+b; }
return b;
end
In other words convert recursion to iteration.

I think the question in already ambiguous.
The sum of all even valued should be below 4 million, or should the biggest even valued number be below 4 million?

Related

LeetCode 264. Ugly Number II - custom Ugly Number finding algorithm [duplicate]

This question already has answers here:
nᵗʰ ugly number
(13 answers)
Closed 2 years ago.
I am trying to solve the LeetCode ugly number challenge II. I came up with an algorithm of my own, seems working in theory but does not. I want to know why. I implemented this in Java but I write in Python normally, so if you correct the Java code, would appreciate.
The problem statement is:
"Write a program to find the n-th ugly number.
Ugly numbers are positive numbers whose prime factors only include 2,
3, 5.
Example:
Input: n = 10 Output: 12 Explanation: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12
is the sequence of the first 10 ugly numbers. Note:
1 is typically treated as an ugly number. n does not exceed 1690."
This is my code:
class Solution {
public int nthUglyNumber(int n) {
// Gather all the uglies in one place
int[] uglies = new int[n];
// Set first one as one
uglies[0] = 1;
// Start filling
for (int i = 1; i < uglies.length - 1; i++) {
int num = i;
if (isUgly(num) == true) {
uglies[i] = num;
} else {
while (isUgly(num) == false) {
num++;
}
uglies[i] = num;
System.out.println(uglies[i]);
}
}
return uglies[uglies.length - 1];
}
public boolean isUgly(int m) {
boolean ans = false;
// Check if the number is divisible by an integer other than 2,3 or 5
// Simply iterate through numbers smaller than n to find a smaller divisor
for (int i = 2; i < m; i++) {
// If n is divisable by i and i is not a multiple of 2,3 or 5
boolean other_divisor = (m % i == 0) && (i % 2 != 0 || i % 3 != 0 || i % 5 != 0);
if (other_divisor == true) {
ans = false;
} else {
ans = true;
}
}
return ans;
}
}
So I basically made a function isUgly(n), which takes a number and checks if it is ugly by finding out if it has a divisor other than 2,3,5. If there is, then it should not be an ugly number. Than in the main body I go over all integers and check if they are ugly. If they are, I add them to an array until I fill out the n-th position. Would appreciate if corrected.
Not sure where your bug is. But, it has to be solved efficiently (time and space).
These solutions would pass through LeetCode, yet are not the most efficient algorithms for the problem. Since the question is math related, pretty sure there are many ways to make it much efficient.
C++
#include <vector>
class Solution {
public:
int nthUglyNumber(int n) {
int factor_two = 0;
int factor_three = 0;
int factor_five = 0;
std::vector<int> uglies(n);
uglies[0] = 1;
for (int index = 1; index < n; index++) {
uglies[index] = std::min(uglies[factor_five] * 5, std::min(uglies[factor_two] * 2, uglies[factor_three] * 3));
if (uglies[index] == uglies[factor_two] * 2) {
factor_two++;
}
if (uglies[index] == uglies[factor_three] * 3) {
factor_three++;
}
if (uglies[index] == uglies[factor_five] * 5) {
factor_five++;
}
}
return uglies[n - 1];
}
};
Java
public class Solution {
public int nthUglyNumber(int n) {
int[] uglies = new int[n];
uglies[0] = 1;
int indexTwo = 0;
int indexThree = 0;
int indexFive = 0;
int two = 2;
int three = 3;
int five = 5;
for (int index = 1; index < n; index++) {
int minFactor = Math.min(five, Math.min(two, three));
uglies[index] = minFactor;
if (minFactor == two) {
two = 2 * uglies[++indexTwo];
}
if (minFactor == three) {
three = 3 * uglies[++indexThree];
}
if (minFactor == five) {
five = 5 * uglies[++indexFive];
}
}
return uglies[n - 1];
}
}
Python
class Solution:
def nthUglyNumber(self, n: int) -> int:
uglies = (1,)
factor_two = factor_three = factor_five = 0
while len(uglies) < n:
while uglies[factor_two] * 2 <= uglies[-1]:
factor_two += 1
while uglies[factor_three] * 3 <= uglies[-1]:
factor_three += 1
while uglies[factor_five] * 5 <= uglies[-1]:
factor_five += 1
curr_ugly = min(uglies[factor_two] * 2, uglies[factor_three] * 3, uglies[factor_five] * 5)
uglies += (curr_ugly,)
return uglies[-1]
References
For additional details, you can see the Discussion Board. There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time/space complexity analysis1, 2 in there.
If you are preparing for interviews:
We would want to write bug-free and clean codes based on standards and conventions (e.g., c1, 2, c++1, 2, java1, 2, c#1, 2, python1, javascript1, go1, rust1). Overall, we would like to avoid anything that might become controversial for interviews.
There are also other similar platforms, which you might have to become familiar with, in case you'd be interviewing with specific companies that would use those platforms.
If you are practicing for contests1:
Just code as fast as you can, almost everything else is very trivial.
For easy questions, brute force algorithms usually get accepted. For interviews, brute force is less desired, especially if the question would be an easy level.
For medium and hard questions, about 90% of the time, brute force algorithms fail mostly with Time Limit Exceeded (TLE) and less with Memory Limit Exceeded (MLE) errors.
Contestants are ranked based on an algorithm explained here.

How to calculate the probability of getting the sum X using N six-sided dice

The Challenge:
For example, what is the probability of getting the sum of 15 when using 3 six-sided dice. This can be for example by getting 5-5-5 or 6-6-3 or 3-6-6 or many more options.
A brute force solution for 2 dice - with complexity of 6^2:
Assuming we had only 2 six-sided dice, we can write a very basic code like that:
public static void main(String[] args) {
System.out.println(whatAreTheOdds(7));
}
public static double whatAreTheOdds(int wantedSum){
if (wantedSum < 2 || wantedSum > 12){
return 0;
}
int wantedFound = 0;
int totalOptions = 36;
for (int i = 1; i <= 6; i++) {
for (int j = 1; j <= 6; j++) {
int sum = i+j;
if (sum == wantedSum){
System.out.println("match: " + i + " " + j );
wantedFound +=1;
}
}
}
System.out.println("combinations count:" + wantedFound);
return (double)wantedFound / totalOptions;
}
And the output for 7 will be:
match: 1 6
match: 2 5
match: 3 4
match: 4 3
match: 5 2
match: 6 1
combination count:6
0.16666666666666666
The question is how to generalize the algorithm to support N dice:
public static double whatAreTheOdds(int wantedSum, int numberOfDices)
Because we can't dynamically create nested for loops, we must come with a different approach.
I thought of something like that:
public static double whatAreTheOdds(int sum, int numberOfDices){
int sum;
for (int i = 0; i < numberOfDices; i++) {
for (int j = 1; j <= 6; j++) {
}
}
}
but failed to come up with the right algorithm.
Another challenge here is - is there a way to do it efficiently, and not in a complexity of 6^N?
Here is a recursive solution with memoization to count the combinations.
import java.util.Arrays;
import java.lang.Math;
class Dices {
public static final int DICE_FACES = 6;
public static void main(String[] args) {
System.out.println(whatAreTheOdds(40, 10));
}
public static double whatAreTheOdds(int sum, int dices) {
if (dices < 1 || sum < dices || sum > DICE_FACES * dices) return 0;
long[][] mem = new long[dices][sum];
for (long[] mi : mem) {
Arrays.fill(mi, 0L);
}
long n = whatAreTheOddsRec(sum, dices, mem);
return n / Math.pow(DICE_FACES, dices);
}
private static long whatAreTheOddsRec(int sum, int dices, long[][] mem) {
if (dices <= 1) {
return 1;
}
long n = 0;
int dicesRem = dices - 1;
int minFace = Math.max(sum - DICE_FACES * dicesRem, 1);
int maxFace = Math.min(sum - dicesRem, DICE_FACES);
for (int i = minFace; i <= maxFace; i++) {
int sumRem = sum - i;
long ni = mem[dicesRem][sumRem];
if (ni <= 0) {
ni = whatAreTheOddsRec(sumRem, dicesRem, mem);
mem[dicesRem][sumRem] = ni;
}
n += ni;
}
return n;
}
}
Output:
0.048464367913724195
EDIT: For the record, the complexity of this algorithm is still O(6^n), this answer just aims to give a possible implementation for the general case that is better than the simplest implementation, using memoization and search space prunning (exploring only feasible solutions).
As Alex's answer notes, there is a combinatorial formula for this:
In this formula, p is the sum of the numbers rolled (X in your question), n is the number of dice, and s is the number of sides each dice has (6 in your question). Whether the binomial coefficients are evaluated using loops, or precomputed using Pascal's triangle, either way the time complexity is O(n2) if we take s = 6 to be a constant and X - n to be O(n).
Here is an alternative algorithm, which computes all of the probabilities at once. The idea is to use discrete convolution to compute the distribution of the sum of two random variables given their distributions. By using a divide and conquer approach as in the exponentiation by squaring algorithm, we only have to do O(log n) convolutions.
The pseudocode is below; sum_distribution(v, n) returns an array where the value at index X - n is the number of combinations where the sum of n dice rolls is X.
// for exact results using integers, let v = [1, 1, 1, 1, 1, 1]
// and divide the result through by 6^n afterwards
let v = [1/6.0, 1/6.0, 1/6.0, 1/6.0, 1/6.0, 1/6.0]
sum_distribution(distribution, n)
if n == 0
return [1]
else if n == 1
return v
else
let r = convolve(distribution, distribution)
// the division here rounds down
let d = sum_distribution(r, n / 2)
if n is even
return d
else
return convolve(d, v)
Convolution cannot be done in linear time, so the running time is dominated by the last convolution on two arrays of length 3n, since the other convolutions are on sufficiently shorter arrays.
This means if you use a simple convolution algorithm, it should take O(n2) time to compute all of the probabilities, and if you use a fast Fourier transform then it should take O(n log n) time.
You might want to take a look at Wolfram article for a completely different approach, which calculates the desired probability with a single loop.
The idea is to have an array storing the current "state" of each dice, starting will every dice at one, and count upwards. For example, with three dice you would generate the combinations:
111
112
...
116
121
122
...
126
...
665
666
Once you have a state, you can easily find if the sum is the one you are looking for.
I leave the details to you, as it seems a useful learning exercise :)

Recursive method for a specific sequence

I am trying to get the value of a sequence at a specific position (where the sequence starts at 0). The formula for this sequence is f(n) = (2^n) - 1 where f(0) = 0.
The sequence goes f(0) = 0, f(1) = 1, f(2) = 3, f(3) = 7, f(4) = 15, etc ...
I wrote this recursive function to find the position. However, my numbers are a bit off. Why are my numbers off?
For this result, if I put in the number f(4), I get the value of what is in f(5) -- 31.
public static int getNumber(int num) {
if(num == 0) {
return 1;
} else {
return (int)Math.pow(2,num) + getNumber(num-1);
}
}
I understand that the problem lays within my base case. How can I fix it?
You said f(0) = 0, but your code checks if num == 0, and if it is, returns 1. You just need to return 0 if num == 0.
Although I don't think your recursion will work correctly the way you want it to, either. 2^n - 1 can be expressed as the sum of all powers of 2 less than n, and yours sums up the powers of two less than or equal to n. So you should probably be taking Math.pow(2, num - 1) while you're at it.
Your instructions say f(0) is 0. Also, your function isn't recsursive. I think you wanted 2n - 1 like
public static int getNumber(int num) {
if (num == 0) {
return 0;
}
return (int) (Math.pow(2, num) - 1);
}
I tested it like,
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.printf("f(%d) = %d%n", i, getNumber(i));
}
}
And got your expected results. Of course, you could use a bitshift instead of Math.pow (since it's 2). Like,
public static int getNumber(int num) {
if (num == 0) {
return 0;
}
return (1 << num) - 1;
}
And get the same results.

Given a number N, can N be expressed as the sum of two or more consecutive perfect squares?

At a recent computer programming competition that I was at, there was a problem where you have to determine if a number N, for 1<=N<=1000, is a palindromic square. A palindromic square is number that can be read the same forwards and backwards and can be expressed as the sum of two or more consecutive perfect squares. For example, 595 is a palindrome and can be expressed as 6^2 + 7^2 + 8^2 + 9^2 + 10^2 + 11^2 + 12^2.
I understand how to determine if the number is a palindrome, but I'm having trouble trying to figure out if it can be expressed as the sum of two or more consecutive squares.
Here is the algorithm that I tried:
public static boolean isSumOfSquares(int num) {
int sum = 0;
int lowerBound = 1;
//largest square root that is less than num
int upperBound = (int)Math.floor(Math.sqrt(num));
while(lowerBound != upperBound) {
for(int x=lowerBound; x<upperBound; x++) {
sum += x*x;
}
if(sum != num) {
lowerBound++;
}
else {
return true;
}
sum=0;
}
return false;
}
My approach sets the upper boundary to the closest square root to the number and sets the lower bound to 1 and keeps evaluating the sum of squares from the lower bound to the upper bound. The issue is that only the lower bound changes while the upper bound stays the same.
This should be an efficient algorithm for determining if it's a sum of squares of consecutive numbers.
Start with a lower bound and upper bound of 1. The current sum of squares is 1.
public static boolean isSumOfSquares(int num) {
int sum = 1;
int lowerBound = 1;
int upperBound = 1;
The maximum possible upper bound is the maximum number whose square is less than or equal to the number to test.
int max = (int) Math.floor(Math.sqrt(num));
While loop. If the sum of squares is too little, then add the next square, incrementing upperBound. If the sum of squares is too high, then subtract the first square, incrementing lowerBound. Exit if the number is found. If it can't be expressed as the sum of squares of consecutive numbers, then eventually upperBound will exceed the max, and false is returned.
while(sum != num)
{
if (sum < num)
{
upperBound++;
sum += upperBound * upperBound;
}
else if (sum > num)
{
sum -= lowerBound * lowerBound;
lowerBound++;
}
if (upperBound > max)
return false;
}
return true;
Tests for 5, 11, 13, 54, 181, and 595. Yes, some of them aren't palindromes, but I'm just testing the sum of squares of consecutive numbers part.
1: true
2: false
3: false
4: true
5: true
11: false
13: true
54: true
180: false
181: true
595: true
596: false
Just for play, I created a Javascript function that gets all of the palindromic squares between a min and max value: http://jsfiddle.net/n5uby1wd/2/
HTML
<button text="click me" onclick="findPalindromicSquares()">Click Me</button>
<div id="test"></div>
JS
function isPalindrome(val) {
return ((val+"") == (val+"").split("").reverse().join(""));
}
function findPalindromicSquares() {
var max = 1000;
var min = 1;
var list = [];
var done = false,
first = true,
sum = 0,
maxsqrt = Math.floor(Math.sqrt(max)),
sumlist = [];
for(var i = min; i <= max; i++) {
if (isPalindrome(i)) {
done = false;
//Start walking up the number list
for (var j = 1; j <= maxsqrt; j++) {
first = true;
sum = 0;
sumlist = [];
for(var k = j; k <= maxsqrt; k++) {
sumlist.push(k);
sum = sum + (k * k);
if (!first && sum == i) {
list.push({"Value":i,"Sums":sumlist});
done = true;
}
else if (!first && sum > i) {
break;
}
first = false;
if (done) break;
}
if (done) break;
}
}
}
//write the list
var html = "";
for(var l = 0; l < list.length; l++) {
html += JSON.stringify(list[l]) + "<br>";
}
document.getElementById("test").innerHTML = html;
}
Where min=1 and max=1000, returns:
{"Value":5,"Sums":[1,2]}
{"Value":55,"Sums":[1,2,3,4,5]}
{"Value":77,"Sums":[4,5,6]}
{"Value":181,"Sums":[9,10]}
{"Value":313,"Sums":[12,13]}
{"Value":434,"Sums":[11,12,13]}
{"Value":505,"Sums":[2,3,4,5,6,7,8,9,10,11]}
{"Value":545,"Sums":[16,17]}
{"Value":595,"Sums":[6,7,8,9,10,11,12]}
{"Value":636,"Sums":[4,5,6,7,8,9,10,11,12]}
{"Value":818,"Sums":[2,3,4,5,6,7,8,9,10,11,12,13]}
An updated version which allows testing individual values: http://jsfiddle.net/n5uby1wd/3/
It only took a few seconds to find them all between 1 and 1,000,000.
You are looking for S(n, k) = n^2 + (n + 1)^2 + (n + 2)^2 + ... (n + (k - 1))^2 which adds up to a specified sum m, i.e., S(n, k) = m. (I'm assuming you'll test for palindromes separately.) S(n, k) - m is a quadratic in n. You can easily work out an explicit expression for S(n, k) - m, so solve it using the quadratic formula. If S(n, k) - m has a positive integer root, keep that root; it gives a solution to your problem.
I'm assuming you can easily test whether a quadratic has a positive integer root. The hard part is probably determining whether the discriminant has an integer square root; I'm guessing you can figure that out.
You'll have to look for k = 2, 3, 4, .... You can stop when 1 + 4 + 9 + ... + k^2 > m. You can probably work out an explicit expression for that.
since there are only few integer powers, you can create an array of powers.
Then you can have 1st and last included index. Initially they are both 1.
while sum is lower than your number, increase last included index. Update sum
while sum is higher, increase 1st included index. Update sum
Or without any array, as in rgettman's answer
Start with an array of The first perfect squares, Let's say your numbers are 13 and 17 , then your array will contain: 1, 4, 9, and 16
Do this kind of checking:
13 minus 1 (0^2) is 12. 1 is a perfect square, 12 is not.
13 minus 2(1^2) is 11. 2 is a perfect square, 11 is not.
13 minus 4(2^2) is 9. 4 is a perfect square, 9 is a perfect square, so 13 is the sum of two perfect
17 minus 1 is 16. 1 and 16 are perfect squares. Eliminate choice.
Keep going until you find one that is not the sum of two perfect squares or not.
One method (probably not efficient) I can think of off the top of my head is,
Suppose N is 90.
X=9 (integer value of sqrt of 90)
1. Create an array of all the integer powers less than x [1,4,9,16,25,36,49,64,81]
2. Generate all possible combinations of the items in the array using recursion. [1,4],[1,9],[1,16],....[4,1],[4,9],....[1,4,9]....3. For each combination (as you generate)- check if the sum of add up to N
**To save memory space, upon generating each instance, you can verify if it sums up to N. If not, discard it and move on to the next.
One of the instances will be [9,81] where 9+81=[90]
I think you can determine whether a number is a sum of consecutive squares quickly in the following manner, which vastly reduces the amount of arithmetic that needs to be done. First, precompute all the sums of squares and place them in an array:
0, 0+1=1, 1+4=5, 5+9=14, 14+16=30, 30+25=55, 55+36=91, ...
Now, if a number is the sum of two or more consecutive squares, we can complete it by adding a number from the above sequence to obtain another number in the above sequence. For example, 77=16+25+36, and we can complete it by adding the listed number 14=0+1+4+9 to obtain the listed number 91=14+77=(0+1+4+9)+(16+25+36). The converse holds as well, provided the two listed numbers are at least two positions apart on the list.
How long does our list have to be? We can stop when we add the first square of n which satisfies (n-1)^2+n^2 > max where max in this case is 1000. Simplifying, we can stop when 2(n-1)^2 > max or n > sqrt(max/2) + 1. So for max=1000, we can stop when n=24.
To quickly test membership in the set, we should hash the numbers in the list as well as storing them in the list; the value of the hash should be the location of the number in the list so that we can quickly locate its position to determine whether it is at least two positions away from the starting point.
Here's my suggestion in Java:
import java.util.HashMap;
public class SumOfConsecutiveSquares {
// UPPER_BOUND is the largest N we are testing;
static final int UPPER_BOUND = 1000;
// UPPER_BOUND/2, sqrt, then round up, then add 1 give MAX_INDEX
static final int MAX_INDEX = (int)(Math.sqrt(UPPER_BOUND/2.0)) + 1 + 1;
static int[] sumsOfSquares = new int[MAX_INDEX+1];
static HashMap<Integer,Integer> sumsOfSquaresHash
= new HashMap<Integer,Integer>();
// pre-compute our list
static {
sumsOfSquares[0] = 0;
sumsOfSquaresHash.put(0,0);
for (int i = 1; i <= MAX_INDEX; ++i) {
sumsOfSquares[i] = sumsOfSquares[i-1] + i*i;
sumsOfSquaresHash.put(sumsOfSquares[i],i);
}
}
public static boolean isSumOfConsecutiveSquares(int N) {
for (int i=0; i <= MAX_INDEX; ++i) {
int candidate = sumsOfSquares[i] + N;
if (sumsOfSquaresHash.containsKey(candidate)
&& sumsOfSquaresHash.get(candidate) - i >= 2) {
return true;
}
}
return false;
}
public static void main(String[] args) {
for (int i=0; i < 1000; ++i) {
if (isSumOfConsecutiveSquares(i)) {
System.out.println(i);
}
}
}
}
Each run of the function performs at most 25 additions and 25 hash table lookups. No multiplications.
To use it efficiently to solve the problem, construct 1, 2, and 3-digit palindromes (1-digit are easy: 1, 2, ..., 9; 2-digit by multiplying by 11: 11, 22, 33, ..., 99; 3-digit by the formula i*101 + j*10. Then check the palindromes with the function above and print out if it returns true.
public static boolean isSumOfSquares(int num) {
int sum = 0;
int lowerBound = 1;
//largest square root that is less than num
int upperBound = (int)Math.floor(Math.sqrt(num));
while(lowerBound != upperBound) {
sum = 0
for(int x=lowerBound; x<upperBound; x++) {
sum += x * x;
}
if(sum != num) {
lowerBound++;
}
else {
return true;
}
}
return false;
}
Perhaps I am missing the point, but considering N, for 1<=N<=1000 the most efficient way would be to solve the problem some way (perhaps brute force) and store the solutions in a switch.
switch(n){
case 5:
case 13:
...
return true;
default:
return false;
}
public static boolean validNumber(int num) {
if (!isPalindrome(num))
return false;
int i = 1, j = 2, sum = 1*1 + 2*2;
while (i < j)
if (sum > num) {
sum = sum - i*i; i = i + 1;
} else if (sum < num) {
j = j + 1; sum = sum + j*j;
} else {
return true;
}
return false;
}
However There Are Only Eleven "Good Numbers" { 5, 55, 77, 181, 313, 434, 505, 545, 595, 636, 818 }. And This Grows Very Slow, For N = 10^6, There Are Only 59.

Optimizing recursive method

I have some code that needs to run with some rather large numbers, and it involves incrementing into a recursive method and is therefor very slow to the point where I can't even get to my desired answer. Could someone help me optimize it? I am a beginner though, so I can't do anything very complex/difficult.
public class Euler012{
public static void main(String[]args){
int divisors=0;
for(long x=1;divisors<=501;x++){
divisors=1;
long i=triangle(x);
for(int n=1;n<=i/2;n++){
if(i%n==0){
divisors++;
}
}
//System.out.println(divisors+"\n"+ i);
System.out.println(i+": " + divisors);
}
}
public static long triangle(long x){
long n=0;
while(x>=0){
n+=x;
x--;
triangle(x);
}
return n;
}
}
First: i don't think its an optimization problem, because its a small task, but as mentioned in the comments you do many unnecessary things.
Ok, now lets see where you can optimize things:
recursion
recursion has usually a bad performance, especially if you don't save values this would be possible in your example.
e.g.: recursive triangle-number function with saving values
private static ArrayList<Integer> trianglenumbers = new ArrayList<>();
public static int triangleNumber(int n){
if(trianglenumbers.size() <= n){
if(n == 1)
trianglenumbers.add(1);
else
trianglenumbers.add(triangleNumber(n-1) + n);
}
return trianglenumbers.get(n-1);
}
but as mentioned by #RichardKennethNiescior you can simply use the formula:
(n² + n)/2
but here we can do optimization too!
you shouldnt do /2 but rather *0.5 or even >>1(shift right)
but most compilers will do that for you, so no need to make your code unreadable
your main method
public static void main(String[]args){
int divisors = 0; //skip the = 0
for(long x=1;divisors<=501;++x){ // ++x instead of x++
divisors=0;
long i=(x*x + x) >> 1; // see above, use the one you like more
/*how many divisors*/
if(i == 1) divisors = 1;
else{ /*1 is the only number with just one natural divisor*/
divisors = 2; // the 1 and itself
for(int n = 2; n*n <= i; ++n){
if(n*n == i) ++divisors;
else if(i%n == 0) divisors += 2;
}
}
System.out.println(i+": " + divisors);
}
}
the ++x instead of x++ thing is explained here
the how many divisors part:
every number except 1 has at least 2 divisors (primes, the number itself and one)
to check how many divisors a number has, we just need to go to the root of the number
(eg. 36 -> its squareroot is 6)
36 has 9 divisors (4 pares) {1 and 36, 2 and 18, 3 and 12, 4 and 8, 6 (and 6)}
1 and 36 are skiped (for(**int n = 2**)) but counted in divisors = 2
and the pares 2, 3 and 4 increase the number of divisors by 2
and if its a square number (n*n == i) then we add up 1
You dont have to generate a new triangle number from scratch each time, if you save the value to a variable, and then add x to it on the next iteration, you dont really need to have the triangle method at all.

Categories

Resources