Why is my recursive memoized Fibonacci code wrong? - java

Something in the main function is wrong, but I don't know what. If I go through the code with a debugger I can see that my code isn't even reaching the fibonacci function right now.
public class Fibonacci {
public static void main(String[] args) {
for (int n=1; n<50; n++) {
System.out.println("Element "+ n + " of the sequence: " + newFib(n));
}
}
public static ArrayList<BigInteger> memo = new ArrayList<BigInteger>();
static BigInteger newFib(int n){
assert n >= 1: "the fibonacci sequence starts at 1";
BigInteger result=BigInteger.valueOf(1);
if (memo.get(n) != null) {
return memo.get(n);
}
else if( n == 1 || n == 2 ) {
memo.add(n, BigInteger.valueOf(1));
return BigInteger.valueOf(1);
}
else {
result= newFib(n-1).add(newFib(n-2));
memo.add(n,result);
return result;
}
}
}

Your code was throwing some exceptions. You simply needed to debug the exceptions and implement the proper checks. Using the code with these changes should work as intended:
import java.math.*;
import java.util.ArrayList;
public class Fibonacci {
public static void main(String[] args) {
for (int n=1; n<50; n++) {
System.out.println("Element "+ n + " of the sequence: " + newFib(n));
}
}
public static ArrayList<BigInteger> memo = new ArrayList<BigInteger>();
static BigInteger newFib(int n){
assert n >= 1: "the fibonacci sequence starts at 1";
BigInteger result=BigInteger.valueOf(1);
if (memo.size() - 1 >= n && memo.get(n) != null) {
return memo.get(n);
}
else if( n == 1 || n == 2 ) {
memo.add(n-1, BigInteger.valueOf(1));
return BigInteger.valueOf(1);
}
else {
result= newFib(n-1).add(newFib(n-2));
memo.add(n,result);
return result;
}
}
}

Your current code does not handle out of bounds correctly and as I mentioned in the comments, the fibonacci sequence does not necessarily start at one and the logic can be simplified. I would use a HashMap<Integer, BigInteger> for storing the memoization and I would also prefer to populate the initial constants once (and as constants). For example,
private static Map<Integer, BigInteger> memo = new HashMap<>();
static {
memo.put(0, BigInteger.ZERO);
memo.put(1, BigInteger.ONE);
}
static BigInteger newFib(int n) {
if (!memo.containsKey(n)) {
if (n < 0) {
memo.put(n, newFib(n + 2).subtract(newFib(n + 1)));
} else {
memo.put(n, newFib(n - 2).add(newFib(n - 1)));
}
}
return memo.get(n);
}
Which can then be tested like
public static void main(String[] args) {
for (int i = -8; i < 9; i++) {
if (i != -8) {
System.out.print(" ");
}
System.out.printf("%-5s", String.format("F(%d)", i));
}
System.out.println();
for (int i = -8; i < 9; i++) {
if (i != -8) {
System.out.print(" ");
}
System.out.printf("%-5s", newFib(i));
}
}
To reproduce the example given in the Fibonacci number Wikipedia entry.
F(-8) F(-7) F(-6) F(-5) F(-4) F(-3) F(-2) F(-1) F(0) F(1) F(2) F(3) F(4) F(5) F(6) F(7) F(8)
-21 13 -8 5 -3 2 -1 1 0 1 1 2 3 5 8 13 21

Related

Struggling to understand recursive backtracking in Java

I am not understanding how recursive backtracking works. We did this example in class, but I don't understand why it backtracks when it is always adding 1 to level or i. Why don't we have to subtract at some point to actually go back through the array? Also, why do 2 recursive calls work, and not produce some kind of error?
public class Subsets {
public static void main(String[] args) {
int[] arr = {3,7,12};
printSubsets(arr);
}
public static void printSubsets(int[] a) {
boolean[] inSet = new boolean[a.length];
printSubsets(a, inSet, 0);
}
public static void printSubsets(int[] a, boolean[] inSet, int level) {
if(level == a.length) {
System.out.print("{");
int i = 0;
while(i < inSet.length && !inSet[i]) {
i++;
}
if(i < inSet.length) {
System.out.print(a[i]);
i++;
for(; i < inSet.length; i++) {
if(inSet[i])
System.out.print(", " + a[i]);
}
}
System.out.print("}");
System.out.println();
}
else {
//System.out.println(level + " " + inSet[level] + " ");
inSet[level] = false;
printSubsets(a, inSet, level+1);
inSet[level] = true;
printSubsets(a, inSet, level+1);
}
}
}

Algorithm to find `balanced number` - the same number of even and odd dividers

We define balanced number as number which has the same number of even and odd dividers e.g (2 and 6 are balanced numbers). I tried to do task for polish SPOJ however I always exceed time.
The task is to find the smallest balance number bigger than given on input.
There is example input:
2 (amount of data set)
1
2
and output should be:
2
6
This is my code:
import java.math.BigDecimal;
import java.util.Scanner;
public class Main {
private static final BigDecimal TWO = new BigDecimal("2");
public static void main(String[] args) throws java.lang.Exception {
Scanner in = new Scanner(System.in);
int numberOfAttempts = in.nextInt();
for (int i = 0; i < numberOfAttempts; i++) {
BigDecimal fromNumber = in.nextBigDecimal();
findBalancedNumber(fromNumber);
}
}
private static boolean isEven(BigDecimal number){
if(number.remainder(new BigDecimal("2")).compareTo(BigDecimal.ZERO) != 0){
return false;
}
return true;
}
private static void findBalancedNumber(BigDecimal fromNumber) {
BigDecimal potentialBalancedNumber = fromNumber.add(BigDecimal.ONE);
while (true) {
int evenDivider = 0;
int oddDivider = 1; //to not start from 1 as divisor, it's always odd and divide potentialBalancedNumber so can start checking divisors from 2
if (isEven(potentialBalancedNumber)) {
evenDivider = 1;
} else {
oddDivider++;
}
for (BigDecimal divider = TWO; (divider.compareTo(potentialBalancedNumber.divide(TWO)) == -1 || divider.compareTo(potentialBalancedNumber.divide(TWO)) == 0); divider = divider.add(BigDecimal.ONE)) {
boolean isDivisor = potentialBalancedNumber.remainder(divider).compareTo(BigDecimal.ZERO) == 0;
if(isDivisor){
boolean isEven = divider.remainder(new BigDecimal("2")).compareTo(BigDecimal.ZERO) == 0;
boolean isOdd = divider.remainder(new BigDecimal("2")).compareTo(BigDecimal.ZERO) != 0;
if (isDivisor && isEven) {
evenDivider++;
} else if (isDivisor && isOdd) {
oddDivider++;
}
}
}
if (oddDivider == evenDivider) { //found balanced number
System.out.println(potentialBalancedNumber);
break;
}
potentialBalancedNumber = potentialBalancedNumber.add(BigDecimal.ONE);
}
}
}
It seems to work fine but is too slow. Can you please help to find way to optimize it, am I missing something?
As #MarkDickinson suggested, answer is:
private static void findBalancedNumberOptimized(BigDecimal fromNumber) { //2,6,10,14,18,22,26...
if(fromNumber.compareTo(BigDecimal.ONE) == 0){
System.out.println(2);
}
else {
BigDecimal result = fromNumber.divide(new BigDecimal("4")).setScale(0, RoundingMode.HALF_UP).add(BigDecimal.ONE);
result = (TWO.multiply(result).subtract(BigDecimal.ONE)).multiply(TWO); //2(2n-1)
System.out.println(result);
}
}
and it's finally green, thanks Mark!

Fibonacci Recursive returns endless number

My code results with endless number "2", I don't understand why.
Also my tutor told me to add validation for negative values - I don't know how to do it.
public class FibonacciRecursive {
public static void main(String[] args) {
int fibonacciNumberOrder = 10;
do {
System.out.print(fibonacci(fibonacciNumberOrder) + " ");
} while (true);
}
public static long fibonacci(int fibonacciNumberInOrder) {
if (fibonacciNumberInOrder == 0) {
return 0;
}
if (fibonacciNumberInOrder <= 2) {
return 1;
}
long fibonacci = fibonacci(-1) + fibonacci(-2);
return fibonacci;
}
}
edit:
When I changed that line
long fibonacci = fibonacci(-1) + fibonacci(-2);
to:
long fibonacci = fibonacci(fibonacciNumberInOrder-1) + fibonacci(fibonacciNumberInOrder-2);
It prints endless "55"
How should I change my code to make it work?
It happens because you calculate the Fibonacci number with constants instead of relative numbers to passed ones through, which is the point of recursion.
public static long fibonacci(int fibonacciNumberInOrder) {
if (fibonacciNumberInOrder == 0) {
return 0;
}
if (fibonacciNumberInOrder <= 2) {
return 1;
}
long fibonacci = fibonacci(fibonacciNumberInOrder - 1) + fibonacci(fibonacciNumberInOrder - 2);
return fibonacci;
}
The key changed line is:
long fibonacci = fibonacci(fibonacciNumberInOrder-1) + fibonacci(fibonacciNumberInOrder-2);
You are recursing with constants! Change this
long fibonacci = fibonacci(-1) + fibonacci(-2);
to
long fibonacci = fibonacci(fibonacciNumberInOrder-1) + fibonacci(fibonacciNumberInOrder-2);
And, in your while loop in main - you need to modify fibonacciNumberInOrder
int fibonacciNumberOrder = 1;
do {
System.out.print(fibonacci(fibonacciNumberOrder) + " ");
fibonacciNumberOrder++;
} while (true);

Prime factorization using GUI (swing/awt)

This code uses Swing and awt to compute prime factorization, the code works, but it shows only one prime factor, for example: if i compute 56 the answer is just 7, how can i fix it?
thanks in advance
calculate6.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Get values from text fields
try {
int a = Integer.parseInt(input1.getText());
result.setText(String.valueOf(a + " "));
for (int i = 2; i <= a; i++) {
while (a % i == 0) {
result.setText(String.valueOf(i + " "));
// System.out.println(i + " ");
a = a / i;
}
}
if (a < 1)
result.setText(String.valueOf(a + " "));
// System.out.println(a + " ");
}
catch (Exception f) {
JOptionPane.showMessageDialog(rootPane, "ERROR: " + (f.getMessage()));
}
String aField = input1.getText();
if (e.getSource() == calculate6) {
if ("".equals(aField)) {
String emptyFieldWarning;
emptyFieldWarning = "One field is empty!";
JOptionPane.showMessageDialog(rootPane, emptyFieldWarning);
}
}
}
});
Edit 1: i have changed the operation part
Your Swing part is fine. If you just try to execute
int a = 56;
for(int i = 2; i< a; i++) {
while (a % i == 0) {
a = a / i;
}
}
System.out.println(a);
you get 7,so the problem is in this part, you shoul look over here
Problem is in the while loop. It is not accumulating the factors. Try this getPrimeFactors() in this sample program.
import java.util.*;
public class PrimeFactors {
public static void main(String[] args) {
System.out.println("56 -> " + PrimeFactors.getPrimeFactors(56));
System.out.println("30 -> " + PrimeFactors.getPrimeFactors(30));
System.out.println("154 -> " + PrimeFactors.getPrimeFactors(154));
}
public static List<Integer> getPrimeFactors(int input) {
List<Integer> factors = new ArrayList<>();
for (int i = 2; i <= input; i++) {
while (input%i == 0) {
input = input/i;
factors.add(i);
}
}
return factors;
}
}
public static final IntFunction<String> getPrimeFactorsAsString = num -> {
List<Integer> res = new ArrayList<>();
for (int i = 2, sqrt = (int)Math.sqrt(num); i <= sqrt; i++) {
while (num % i == 0) {
res.add(i);
num /= i;
}
}
return res.stream().map(String::valueOf).collect(Collectors.joining(" "));
};
Demo
System.out.println(getPrimeFactorsAsString.apply(56)); // 2 2 2 7
System.out.println(getPrimeFactorsAsString.apply(660)); // 2 2 3 5 11

Recursively splitting off perfect squares for display

I am attempting to create a recursive method that accepts an integer parameter and prints the first n squares
separated by commas, with the odd squares in descending order followed by the even squares in ascending order.
For example, if the input is 8, it should print the following output:
49, 25, 9, 1, 4, 16, 36, 64
My code so far is:
s and n have the same values initially, the only difference is that s changes as the code forwards while n doesn't change.
private static void genSquare(int s, int n) {
if (s >= 0 && s <= n) {
if (isOdd(s)) {
System.out.print(Math.pow(n, 2) + " ");
genSquare(s - 2, n);
}
if (s == 0 || s == 1) {
genSquare(1, n);
}
if (isEven(s)) {
System.out.print(Math.pow(n, 2) + " ");
genSquare(s + 2, n);
}
}
}
I have created a while loop version of it, which works perfectly. I just don't have the recursive version working.
Sample inputs would be using the same number for s and n.
Here is the code for the loop version:
private void genLoop(int s, int n) {
if (isEven(s)) {
s--;
}
while (s <= n) {
if (s == 1) {
System.out.print(1 + " ");
s++;
} else if (isOdd(s)) {
System.out.print(s * s + " ");
s -= 2;
} else if (isEven(s)) {
System.out.print(s * s + " ");
s += 2;
}
}
}
The problem is in this statement:
if(s == 0 || s== 1)
genSquare(1,n);
This causes the method to recurse infinitely. In fact, when you get to the point where s is zero or one, you have to make sure that you DON'T call genSquare recursively.
That's enough of a hint for you to figure the rest out for yourself ... and fix any other bugs.
In addition, there's a simpler way of squaring an integer ...
void calculateSquare(int n)
{
// odds descending and even ascending
int t=n;
if(n<=0)
return;
if(n%2==1)
{
// Calculate square now and print it also
System.out.println(n*n);
calculateSquare(--n);
}
else
{
calculateSquare(--n);
System.out.println(t*t);
}
}
This would do the job.
Try the following approach:
Assume your example where n is equal to 8. The square of 8 should printed last so you probably first should do a recursive call, then print the square of the current number.
Thinking about the task for n=7 the order of things given above should be reverted for odd numbers.
Yes it is good example for recursion . Try this it helps u
public class RecursionEx {
static int no = 0;
public static void main(String[] args) {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
System.out.println("Enter the Number");
try
{
no = Integer.parseInt(bufferedReader.readLine());
getSquares(no,0);
}
catch (Exception e)
{
e.printStackTrace();
}
}
private static void getSquares(int number,int count)
{
if(number==1)
{
System.out.print(number);
count=1;
getSquares(number+1, count);
}
else
{
if(number%2!=0&&count==0)
{
System.out.print(number*number+",");
getSquares(number-2,0);
return;
}
if(count==0)
getSquares(number-1,0);
if(number%2==0&&count==1)
{
if(number<=no)
System.out.print(","+number*number);
if(number>=no)
return;
getSquares(number+2, count);
}
}
}
}

Categories