Using recursion, If n is 123, the code should return 4 (i.e. 1+3). But instead it is returning the last digit, in this case 3.
public static int sumOfOddDigits(NaturalNumber n) {
int ans = 0;
if (!n.isZero()) {
int r = n.divideBy10();
sumOfOddDigits(n);
if (r % 2 != 0) {
ans = ans + r;
}
n.multiplyBy10(r);
}
return ans;
}
It isn't clear what NaturalNumber is or why you would prefer it to int, but your algorithm is easy enough to follow with int (and off). First, you want the remainder (or modulus) of division by 10. That is the far right digit. Determine if it is odd. If it is add it to the answer, and then when you recurse divide by 10 and make sure to add the result to the answer. Like,
public static int sumOfOddDigits(int n) {
int ans = 0;
if (n != 0) {
int r = n % 10;
if (r % 2 != 0) {
ans += r;
}
ans += sumOfOddDigits(n / 10);
}
return ans;
}
One problem is that you’re calling multiplyBy on n and not doing anything with the result. NaturalNumber seems likely to be immutable, so the method call has no effect.
But using recursion lets you write declarative code, this kind of imperative logic isn’t needed. instead of mutating local variables you can use the argument list to hold the values to be used in the next iteration:
public static int sumOfOddDigits(final int n) {
return sumOfOddDigits(n, 0);
}
// overload to pass in running total as an argument
public static int sumOfOddDigits(final int n, final int total) {
// base case: no digits left
if (n == 0)
return total;
// n is even: check other digits of n
if (n % 2 == 0)
return sumOfOddDigits(n / 10, total);
// n is odd: add last digit to total,
// then check other digits of n
return sumOfOddDigits(n / 10, n % 10 + total);
}
I'm trying to implement a code that returns the sum of all prime numbers under 2 million. I have an isPrime(int x) method that returns true if the the number is prime. Here it is:
public static boolean isPrime(int x) {
for (int i = 2; i < x; i++) {
if (x % i == 0) {
return false;
}
}
return true;
}
And the other method, which I'm trying to implement recursively, only works until a certain number, over that number and I get a stack overflow error. The highest I got the code to work was for 10,000.
Here it is:
public static int sumOfPrimes(int a) {
if (a < 2000000) { //this is the limit
if (isPrime(a)) {
return a + sumOfPrimes(a + 1);
} else {
return sumOfPrimes(a + 1);
}
}
return -1;
}
So why do I get a stack overflow error when the number gets bigger and how can I deal with this?
Also, how do you normally deal with writing code for such big numbers? IE: normal number operations like this but for larger numbers? I wrote this recursively because I thought it would be more efficient but it still wont work.
Your isPrime function is inefficient, it doesn't have to go to x, it's enough to go to the square root of x.
But that is not the reason why your solution doesn't work. You cannot have a recursion depth of 1 million.
I would solve this problem iteratively, using the sieve of eratosthenes and for loop over the resulting boolean array.
In general if you would still like to use recursion, you can use tail recursion.
In recursion each function call will push some data to the stack, which is limited, thus generating a stackoverflow error. In tail recursion you won't be pushing anything to the stack, thus not throwing the exception.
Basically all you need is sending the data of the previous computation as parameter instead of having it on the stack.
So:
function(int x) {
// end condition
return function(x - 1) + x;
}
with tail recursion would be
function (int max, int curr, int prev, int sum) {
if (curr > max)
return sum;
return function (max, curr + 1, curr, sum + curr)
}
Keep in mind this is just pseudo code not real java code, but is close enough to the java code.
For more info check
What is tail recursion?
Use Sieve of Eratosthenes:-
Following is the algorithm to find all the prime numbers less than or equal to a given integer n by Eratosthenes’ method:
1) Create a list of consecutive integers from 2 to n: (2, 3, 4, …, n).
2) Initially, let p equal 2, the first prime number.
3) Starting from p, count up in increments of p and mark each of these numbers greater than p itself in the list. These numbers will be 2p, 3p, 4p, etc.; note that some of them may have already been marked.
4) Find the first number greater than p in the list that is not marked. If there was no such number, stop. Otherwise, let p now equal this number (which is the next prime), and repeat from step 3.
public static void main(String[] args) {
int n = 30;
System.out.printf("Following are the prime numbers below %d\n", n);
SieveOfEratosthenes(n);
}
static void markMultiples(boolean arr[], int a, int n)
{
int i = 2, num;
while ( (num = i*a) <= n )
{
arr[ num-1 ] = true; // minus 1 because index starts from 0.
++i;
}
}
// A function to print all prime numbers smaller than n
static void SieveOfEratosthenes(int n)
{
// There are no prime numbers smaller than 2
if (n >= 2)
{
// Create an array of size n and initialize all elements as 0
boolean[] arr=new boolean[n];
for(int index=0;index<arr.length-1;index++){
arr[index]=false;
}
for (int i=1; i<n; ++i)
{
if ( arr[i] == false )
{
//(i+1) is prime, print it and mark its multiples
System.out.printf("%d ", i+1);
markMultiples(arr, i+1, n);
}
}
}
}
Output:-
Following are the prime numbers below 30
2 3 5 7 11 13 17 19 23 29
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.
I am working on a homework assignment, and I have completely exhausted myself. I'm new to programming, and this is my first programming class.
this is the problem:
Consider the following recursive function in Collatz.java, which is related to a famous unsolved problem in number theory, known as the Collatz problem or the 3n + 1 problem.
public static void collatz(int n) {
StdOut.print(n + " ");
if (n == 1) return;
if (n % 2 == 0) collatz(n / 2);
else collatz(3*n + 1);}
For example, a call to collatz(7) prints the sequence
7 22 11 34 17 52 26 13 40 20 10 5 16 8 4 2 1
as a consequence of 17 recursive calls. Write a program that takes a command-line argument N and returns the value of n < N for which the number of recursive calls for collatz(n) is maximized. Hint: use memoization. The unsolved problem is that no one knows whether the function terminates for all positive values of n (mathematical induction is no help because one of the recursive calls is for a larger value of the argument).
I have tried several things: using a for loop, trying to count the number of executions with a variable incremented each time the method executed, and hours of drudgery.
Apparently, I'm supposed to use an array somehow with the memoization. However, I don't understand how I could use an array when an array's length must be specified upon initiation.
Am I doing something completely wrong? Am I misreading the question?
Here is my code so far. It reflects an attempt at trying to create an integer array:
public class Collatz2 {
public static int collatz2(int n)
{
StdOut.print(n + " ");
if (n==1) {return 1;}
else if (n==2) {return 1;}
else if (n%2==0) {return collatz2(n/2);}
else {return collatz2(3*n+1);}
}
public static void main(String[] args)
{
int N = Integer.parseInt(args[0]);
StdOut.println(collatz2(N));
}
}
EDIT:
I wrote a separate program
public class Count {
public static void main(String[] args) {
int count = 0;
while (!StdIn.isEmpty()) {
int value = StdIn.readInt();
count++;
}
StdOut.println("count is " + count);
}
}
I then used piping: %java Collatz2 6 | java Count
and it worked just fine.
Since you are interested in the maximum sequence size and not necessarily the sequence itself, it is better to have collatz return the size of the sequence.
private static final Map<Integer,Integer> previousResults = new HashMap<>();
private static int collatz(int n) {
int result = 1;
if(previousResults.containsKey(n)) {
return previousResults.get(n);
} else {
if(n==1) result = 1;
else if(n%2==0) result += collatz(n/2);
else result += collatz(3*n + 1);
previousResults.put(n, result);
return result;
}
}
The memoization is implemented by storing sequence sizes for previous values of n in Map previousResults.
You can look for the maximum in the main function:
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
int maxn=0, maxSize=0;
for(int n=N; n>0; n--) {
int size = collatz(n);
if(size>maxSize) {
maxn = n;
maxSize = size;
}
}
System.out.println(maxn + " - " + maxSize);
}
The trick here is to write a recursive method where an argument is the value you want to "memoize". For instance, here is a version of a method which will return the number of steps needed to reach 1 (it supposes that n is greater than or equal to 1, of course):
public int countSteps(final int n)
{
return doCollatz(0, n);
}
public static int doCollatz(final int nrSteps, final int n)
{
if (n == 1)
return nrSteps;
final int next = n % 2 == 0 ? n / 2 : 3 * n + 1;
return doCollatz(nrSteps + 1, next);
}
If you were to record the different steps instead, you'd pass a List<Integer> as an argument and .add() to it as you went through, etc etc.
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?