Good day!
I just wrote a code as an iteration which is supposed to sum up even numbers in between 0 and y.
I've been sitting now on my desk for about two hours thinking on how to write the same code in a recursion - without any progress so far.
The only explanations I find on the internet explain it for one simple repeat of one specific change - unlike my code which includes two. ("result = result + x;" and "x = x + 2;" )
Could someone please explain to me how I turn this kind of iteration into a recursion? Thanks in advance!
public class Sum {
static int method(int y) {
int result = 0;
for (int x = 2; x<=y;)
{
result = result + x;
x = x + 2;
}
return result;
}
public static void main(String[ ] args) {
int result = method(35);
System.out.println("Sum of even numbers between 0-35: " +result);
}
}
The total of the numbers is the total of this number plus the total of the number minus 2. Written in code:
int method(int y) {
if (y <= 0) {
return 0;
} else {
return y + method(y - 2);
}
}
Needless to say that recursion in this form is not necessary, and will create a StackoverflowException when y is a really large number. Some languages allow you to write a recursive function and indicate it is a tail recursion so that the compiler actually transforms it to an iteration.
Related
I am using the "think java" book and I am stuck on exercise 7.6. The goal here is to write a function that can find . It gives you a couple hints:
One way to evaluate is
to use the infinite series expansion:
In other words, we need to add up a series of terms where the ith term
is equal to
Here is the code I came up with, but it is horribly wrong (when compared to Math.exp) for anything other than a power of 1. I don't understand why, as far as I can tell the code is correct with the formula from the book. I'm not sure if this is more of a math question or something related to how big of a number double and int can hold, but I am just trying to understand why this doesn't work.
public static void main(String[] args) {
System.out.println("Find exp(-x^2)");
double x = inDouble("Enter x: ");
System.out.println("myexp(" + -x*x + ") = " + gauss(x, 20));
System.out.println("Math.exp(" + -x*x + ") = " + Math.exp(-x*x));
}
public static double gauss(double x, int n) {
x = -x*x;
System.out.println(x);
double exp = 1;
double prevnum = 1;
int prevdenom = 1;
int i = 1;
while (i < n) {
exp = exp + (prevnum*x)/(prevdenom*i);
prevnum = prevnum*x;
prevdenom = prevdenom*i;
i++;
}
return exp;
} // I can't figure out why this is so inacurate, as far as I can tell the math is accurate to what the book says the formula is
public static double inDouble(String string) {
Scanner in = new Scanner (System.in);
System.out.print(string);
return in.nextDouble();
}
I am about to add to the comment on your question. I do this because I feel I have a slightly better implementation.
Your approach
Your approach is to have the function accept two arguments, where the second argument is the number of iterations. This isn't bad, but as #JamesKPolk pointed out, you might have to do some manual searching for an int (or long) that won't overflow
My approach
My approach would use something called the machine epsilon for a data type. The machine epsilon is the smallest number of that type (in your case, double) that is representable as that number. There exists algorithm for determining what that machine epsilon is, if you are not "allowed" to access machine epsilon in the Double class.
There is math behind this:
The series representation for your function is
Since it is alternating series, the error term is the absolute value of the first term you choose not to include (I leave the proof to you).
What this means is that we can have an error-based implementation that doesn't use iterations! The best part is that you could implement it for floats, and data types that are "more" than doubles! I present thus:
public static double gauss(double x)
{
x = -x*x;
double exp = 0, error = 1, numerator = 1, denominator = 1;
double machineEpsilon = 1.0;
// calculate machineEpsilon
while ((1.0 + 0.5 * machineEpsilon) != 1.0)
machineEpsilon = 0.5 * machineEpsilon;
int n = 0; //
// while the error is large enough to be representable in terms of the current data type
while ((error >= machineEpsilon) || (-error <= -machineEpsilon))
{
exp += error;
// calculate the numerator (it is 1 if we just start, but -x times its past value otherwise)
numerator = ((n == 0) ? 1 : -numerator * x);
// calculate the denominator (denominator gets multiplied by n)
denominator *= (n++);
// calculate error
error = numerator/denominator;
}
return exp;
}
Let me know how this works!
This is the scenario question:
A frog only moves forward, but it can move in steps 1 inch long or in jumps 2 inches long. A frog can cover the same distance using different combinations of steps and jumps.
Write a function that calculates the number of different combinations a frog can use to cover a given distance.
For example, a distance of 3 inches can be covered in three ways: step-step-step, step-jump, and jump-step.
public class Frog{
public static int numberOfWays(int input) {
int counter = 2;
int x = 0;
for (int i = 1 ; i< input -1; i++ ){
x = i + counter;
counter = x;
}
if (input <3){
x = input;
}
return x;
}
public static void main(String[] args) {
System.out.println(numberOfWays(10));
}
}
This solution only gives me %50 right not sure why its not %100 right, I tested it with other values and returns the right results.
I think recursion is a nice way to solve problems like that
public int numberOfCombinations(int distance) {
if (distance == 1) {
return 1; //step
} else if (distance == 2) {
return 2; // (step + step) or jump
} else {
return numberOfCombinations(distance - 1) + numberOfCombinations(distance - 2);
// we jumped or stepped into the current field
}
}
Let f[n] be the number of combinations of steps and jumps such that you travel n inches. You can immediately see that f[n] = f[n-1] + f[n-2], that is first you can travel n-1 inches in some way and then use 1 step or you can travel n-2 inches in some way and then use 1 jump. Since f[1] = 1 and f[2] = 2 you can see that f[n] = fib(n+1), the n+1-th Fibonacci number. You can calculate it in linear time if it suits the purpose or, more efficiently, you can calculate it in log n time - reference
The problem is a modified version of the Fibonacci series. I get 100% for the following (sorry it's C# but is very similar):
using System;
public class Frog
{
public static int NumberOfWays(int n)
{
int firstnumber = 0, secondnumber = 1, result = 0;
if (n == 1) return 1;
if (n == 2) return 2;
for (int i = 2; i <= n + 1; i++)
{
result = firstnumber + secondnumber;
firstnumber = secondnumber;
secondnumber = result;
}
return result;
}
public static void Main(String[] args)
{
Console.WriteLine(NumberOfWays(3));
Console.WriteLine(NumberOfWays(4));
Console.WriteLine(NumberOfWays(5));
Console.WriteLine(NumberOfWays(6));
Console.WriteLine(NumberOfWays(7));
Console.WriteLine(NumberOfWays(8));
}
}
Think overlapping subproblem / dynamic programming. You need to memorize the repetitive calls to the sub-problem which will save you all the time.
I believe this should cover your all scenarios.
public static string numberOfCombinations(int distance)
{
if (distance == 1) {
return "Step";//1
} else if (distance == 2) {
return "Jump";//2
} else{
return numberOfCombinations(1) + numberOfCombinations(distance - 1);
}
}
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.
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.
This problem has me puzzled. I tried using a loop like this: Basically I tried to get the first digit from the input and do the formula but it doesn't seem to work. It looks so simple but I can't figure it out. Could you help me? Thanks.
public static int ISBN(String ninedigitNum) {
number = 9;
while (number > 0) {
int nextDigit = ninedigitNum.substring(0,1);
...
}
Checksums (Source: Princeton University). The International Standard
Book Number (ISBN) is a 10 digit code that uniquely specifies a book.
The rightmost digit is a checksum digit which can be uniquely
determined from the other 9 digits from the condition that d1 + 2d2 +
3d3 + ... + 10d10 must be a multiple of 11 (here di denotes the ith
digit from the right). The checksum digit d1 can be any value from 0
to 10: the ISBN convention is to use the value X to denote 10.
Example: the checksum digit corresponding to 020131452 is 5 since is
the only value of d1 between 0 and and 10 for which d1 + 2*2 + 3*5 +
4*4 + 5*1 + 6*3 + 7*1 + 8*0 + 9*2 + 10*0 is a multiple of 11. Create a
Java method ISBN() that takes a 9-digit integer as input, computes the
checksum, and returns the 10-digit ISBN number. Create 3 JUnit test
cases to test your method.
I got it, thanks a lot everyone!
What about it isn't working? Either way, I believe what you're missing is that you're continually getting the same substring, which will be the first number of the string: int nextDigit = ninedigitNum.substring(0,1);. In addition, you're going to want to use an int, not a String; you can technically convert from String to int if desired, but the problem itself calls for an int.
There are two ways to do this that jump to mind. I would do this by realizing that mod in powers of 10 will give you the respective digit of an integer, but the easier way is to convert to a char array and then access directly. Note that there's no error checking here; you'll have to add that yourself. In addition, there are a LOT of 'magic numbers' here: good code typically has very, very few. I would recommend learning more data structures before attempting problems like these; to be honest there's very few things you can do without at least arrays and linked lists.
char[] ISBN = ninedigitNum.toCharArray();
//Process each number
int total = 0;
for(int i=0; i<9; i++){
int current_int = Integer.parseInt(ISBN[i]);
total += current_int * (10 - i)
}
//Find value of d1
for(int i=0; i<9; i++){
if(((total + i) % 11) == 0){
total += i*100000000;
break;
}
}
return total;
In general: Use print outs with System.out.println(x); or use your compiler's debugger to see what's going on during processing.
So,
This is the piece of code that I wrote. I still think it could be made more efficient.
public class Problem3 {
public static String ISBN(String x)
{
char[]temp = x.toCharArray();
int counter = 2;
int sum = 0;
int j=0;
for(int i=8;i>=0;i--)
{
sum+= counter*Integer.parseInt(""+temp[i]);
counter+=1;
}
for(j=0;j<10;j++)
{
if((sum+j)%11==0)
{
break;
}
}
return x+""+j;
}
public static void main(String args[])
{
String a = "020131452";
System.out.println(ISBN(a));
}
}
Hope this helps.
This works:
public static int ISBN(String nineDigitNum){
int sum = 0;
for(int i = 0; i<nineDigitNum.length(); i++){
sum += Integer.parseInt(""+nineDigitNum.charAt(i))*(10-i);
}
return (sum%11);
}
Also I believe if the checksum is == to 10, it should return an X, so you could either change the return type and add an if statement somewhere, or just put the if statement outside wherever you are using this method.
Here is a short one without loops that uses only substring(), charAt() and length():
public static String ISBN(String nineDigits) {
int chkD = 11 - checkDigit(nineDigits, 0);
return nineDigits + ((chkD == 10) ? "X" : chkD);
}
public static int checkDigit(String nDsub, int chkD) {
if (nDsub.length() == 0)
return 0;
chkD = ((nDsub.charAt(0) - '0') * (nDsub.length() + 1));
return (chkD + checkDigit(nDsub.substring(1), chkD)) % 11;
}
Output:
> ISBN("123456789")
"123456789X"
> ISBN("123456780")
"1234567806"