Looking for an iterative solution of a recursive one - java

For the following question I implemented both recursive and recursive dynamic solution, however I am interested in an iterative solution ( not recursive). Can anyone help me with that?
Question:
A cat is jumping up a staircase with n steps, and can hop either 1 step, 2 steps, or 3 steps at a
time. Implement a method to count how many possible ways the cat can jump up the stairs.
For iterative solution what I know is that we essentially have to count the leaves of the trinary tree below with value 0
Dynamic and recursive solutions:
import java.util.ArrayList;
public class Question1 {
public static int countAndDisply(int n, ArrayList<Integer> hop) {
if (n<0){
return 0;
}else{
if (n==0) {
for(int i:hop){
System.out.print(i+",");
}
System.out.println();
return 1;
}else{
ArrayList<Integer> hop1 = new ArrayList<>(hop);
hop1.add(1);
ArrayList<Integer> hop2 = new ArrayList<>(hop);
hop2.add(2);
ArrayList<Integer> hop3 = new ArrayList<>(hop);
hop3.add(3);
return countAndDisply(n-1, hop1)+countAndDisply(n-2, hop2)+countAndDisply(n-3, hop3);
}
}
}
/**
* Faster by using dynamic programming techniques to improve speed
* We dont want to calculate the count(n) multiple times!
* #param n
* #param path
* #return
*/
public static int countFast(int n, int[] map){
if (n<0){
return 0;
}else{
if (n==0) {
return 1;
}else{
if (map[n]>0){
return map[n];
}else {
return countFast(n-1, map) + countFast(n-2, map) + countFast(n-3, map);
}
}
}
}
public static int count(int n){
if (n<0){
return 0;
}else{
if (n==0) {
return 1;
}else{
return count(n-1) + count(n-2) + count(n-3);
}
}
}
public static void main(String[] args) {
int n=10;
int [] map = new int[n+1];
long startTime = System.nanoTime();
System.out.println("Total number of possiblilities:"+Question1.countFast(n,map));
long totalTime = System.nanoTime()-startTime;
System.out.println("Time needed for dynamic recursive approach was(ns):"+totalTime);
//System.out.println("Total number of possiblilities:"+Question1.AndDisply(n,new ArrayList<Integer>()));
System.out.println("Total number of possiblilities:"+Question1.count(n));
totalTime = System.nanoTime()-startTime;
System.out.println("Time needed for pure recursive was(ns):"+totalTime);
}
}
and here are outputs:
Total number of possiblilities:274
Time needed for dynamic recursive approach was(ns):249311
Total number of possiblilities:274
Time needed for pure recursive was(ns):351088

If you want to do it iterative, the best way is to start from 0, not from n.
An example:
i i-1 i-2 i-3 sum
0 || -1 -2 -3 | 0 # does not contain any solution
1 || 0 -1 -2 | 1 # contains one solution (0)
2 || 1 0 -1 | 2 # contains two solutions (0,1) - (-1,-2)
3 || 2 1 0 | 4 # contains three solutions(0,1,2)
# 2 (2) ,1(1) +1 (0) => 2+1+1 = 4
4 || 3 2 1 | 7 # 3 (4) ,2(2) 1 (1) => 4+2+1 = 7
5 || 4 3 2 | 13 # and so on
6 || 5 4 3 | 24
7 || 6 5 4 | 44
8 || 7 6 5 | 81
9 || 8 7 6 | 149
10 || 9 8 7 | 274
The code is extremely simple:
public static int solve(int n) {
int[] map=new int[n+1];
map[0]=1;
map[1]=1;
map[2]=2;
for (int i = 3; i < map.length; i++) {
map[i]+=map[i-1];
map[i]+=map[i-2];
map[i]+=map[i-3];
}
return map[n];
}
And much faster, of course.

Related

java vector recursion solution generating subsets have different results

I want to generate all subsets of a set from 0 to n.
My code works successfully in c++, but in Java I've got different result
My code in c++:
#include <bits/stdc++.h>
using namespace std;
vector <vector<int>> v;
vector <int> u;
int n,i,j;
void f(vector <int> m,int k){
if(k==n+1){v.push_back(m);return;}
f(m,k+1);
m.push_back(k);
f(m,k+1);
}
int main() {
cin>>n;
f(u,0);
for(i=0;i<v.size();i++){
for(j=0;j<v[i].size();j++)cout<<v[i][j]<<' ';
cout<<endl;
}
}
input in c++: 2
output:
2
1
1 2
0
0 2
0 1
0 1 2
and my code in Java:
import java.util.*;
public class Main {
public static int c=0,j,i,n,l,r,x;
public static Vector <Vector<Integer>> v = new Vector();
public static void f(Vector <Integer> m,int k){
if (k==n+1) {v.add(m);return;}
f(m,k+1);
m.add(k);
f(m,k+1);
}
public static void main(String[] args) {
Scanner scan = new Scanner (System.in);
n=scan.nextInt();
Vector<Integer> u = new Vector<Integer>();
f(u,0);
for(i=0;i<v.size();i++){
for(int j:v.get(i))System.out.print(j+" ");
System.out.print("\n");
}
}
}
input in Java: 2
output:
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
2 1 2 0 2 1 2
As you see code in java is based on same logic but I cannot understand why java version gives me wrong result.
As you see code in java is based on same logic but I cannot Understand Why java code gives me wrong result
There is a big difference between C++ and Java here. In C++, unless you explicitly use vector<int> & v to use the same vector, it will automatically make a copy while in Java you have to explicitly do the copy yourself. Java uses pass-by-value mechanism and you only created one vector and then use it all the way which actually using the same vector.
Your problem lies: using the same vector to collect the elements all the way through.
To solve this problem, you should create a new vector to store the elements when passing in the method as:
public class HelloWorld {
public static int c = 0, j, i, n, l, r, x;
public static Vector<Vector<Integer>> v = new Vector();
// each combination of the elements should have an independent vector;
public static void f(Vector<Integer> m, int k) {
if (k == n + 1) {
v.add(m);
return;
} // the unique vector;
f(new Vector<>(m), k + 1); // create a new vector to store the elements;
m.add(k);
f(new Vector<>(m), k + 1); // same logic applied here;
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
n = scan.nextInt();
Vector<Integer> u = new Vector<Integer>();
f(new Vector<>(), 0);
for (i = 0; i < v.size(); i++) {
for (int j : v.get(i)) System.out.print(j + " ");
System.out.print("\n");
}
}
}
Output can be:
3
3
2
2 3
1
1 3
1 2
1 2 3
0
0 3
0 2
0 2 3
0 1
0 1 3
0 1 2
0 1 2 3

A* 8 puzzle written in Java not working for certain initial states

I had to implement an 8 puzzle solver utilizing the A* algorithm with two heuristics. The first heuristic was just the sum of the out-of-place tiles, the second is the sum of the Manhattan distances of all tiles from the goal state, which we are defining as:
0 1 2
3 4 5
6 7 8
We given were sample tests of varying depths. My implementation using the first heuristic passes all of these cases, but the second heuristic does not pass certain test cases once it reaches depths of 14:
(52) !Test Case failed! for initialState:
3 1 5
6 0 7
8 2 4
Expected depth of 14 but got 16
(12) !Test Case failed! for initialState:
4 1 5
3 2 7
0 8 6
Expected depth of 16 but got 18
(39) !Test Case failed! for initialState:
2 5 7
3 4 1
6 8 0
Expected depth of 16 but got 18
(There are more failed tests, these are just the first three) Since it seems to work for all cases when I use the first heuristic, I'm guessing it's something wrong with the second heuristic. Here is my abstract "node" class:
public EightPuzzleState(int[] state, EightPuzzleState goalState, EightPuzzleState previousState) {
this.state = new int[NUM_SPACES];
try {
System.arraycopy(state, 0, this.state, 0, NUM_SPACES);
}catch(ArrayIndexOutOfBoundsException e){
e.printStackTrace();
}
this.previousState = previousState;
setCost(goalState);
}
private void setCost(EightPuzzleState goalState) {
if(goalState == null) {
System.out.println("Cost is 0- no goal state defined");
cost = 0;
}
else {
cost = calcCost(goalState);
}
}
private int calcCost(EightPuzzleState goalState) {
int sum = 0;
for(int i = 0; i < NUM_SPACES; i++) {
sum+=heuristic(goalState, i);
}
if(previousState == null) {
//System.out.println("No previous parent defined, 0 pathCost");
pathCost = 0;
}
else {
pathCost = previousState.getPathCost()+1;
}
return sum + pathCost;
And here is the node class that utilizes the second heuristic:
//In EightPuzzleStateH2 class, which extends EightPuzzleState
#Override
protected int heuristic(EightPuzzleState goalState, int currentIndex) {
int currentValue = this.getState()[currentIndex];
int[] goalStateArray = goalState.getState();
int i = 0;
while(currentValue != goalStateArray[i]) {
i++;
}
return calcManhattenDistance(currentIndex,i);
}
private int calcManhattenDistance(int currentIndex, int goalIndex) {
int xDistance = Math.abs((currentIndex % NUM_SPACES_PER_ROW) - (goalIndex % NUM_SPACES_PER_ROW));
int yDistance = Math.abs((currentIndex / NUM_SPACES_PER_ROW) - (goalIndex / NUM_SPACES_PER_ROW));
return (xDistance+yDistance);
}
Any insight would be helpful- if the issue isn't within the second heuristic, then I'm really going to be stumped since the first heuristic worked flawlessly!
I was able to fix this issue by modifying my hashcode function for my EightPuzzleState class.
Also, when calculating the heuristic, I was including the hole in the calculation, but the hole should not be included in the cost calculation. This was not related to the problem I was having, but for the sake of other readers I am addressing it here.

Multiply by two then every three years by three

I am working on an assignment that asks:
Magic Plant
We have a magic plant that once it is planted, it germinates and grows two leaves in the first
year. It doubles its leaves every year except that every three years it triples its leaves.
Something like:
Year: 1 | 2 | 3 | 4| 5| 6 | 7 …
Leaves: 2 | 4 | 12| 24| 48|144|288 …
What I have completed so far:
int n = 0;
int l = 6;
for(int i = 2; i>-1; i++) {
if(i == l) {
break;
}
if(i != l) {
n = 2 * i;
}
if(i == l) {
break;
}
if(i != l) {
n = 3 * i;
}
System.out.println(n);
}
My thought process behind that was to check if it passed the year 6 before it multiplied it by two and then by three on the third year, then repeat.
This does not work the output is:
3
6
9
15
I need to be able to input a year and find a number of leaves,
as well as take the number of leaves and find out how old the plant is.
public static void main(String [] args)
{
String years = "";
String leave = "";
int num_years = 10;
int leave_count = 1;
for(int i=1;i<= num_years;i++) {
leave_count = (i%3 == 0)? leave_count * 3:leave_count*2;
years = years + i +"|";
leave = leave + leave_count + "|";
}
System.out.println(years+"\n"+leave);
}
how about this:
int years = 30; //number of years
long leaves = 0; //long is better because int will overflow faster
for(int i = 0 ; i < years ; ++i){
if(i == 0)//first year
leaves += 2;//adds 2 leaves
else if(i % 3 == 0) //Every third year
leaves *= 3; //triple leaves
else//every other year
leaves *= 2; //doubles leaves
System.out.println(leaves);
}
will print:
2
4
8
24
48
96
288
576
...
Test the code here
You could use the mod or remainder operator (%), it's pretty handy for this kind of tasks.
I recommend using better names for your variables since it can be detrimental in the long run; use self explanatory names like numberOfLeaves instead of n and sixthYear instead of l.
Using this knowledge you could get the number of years of the tree, since it's an assignment (for collegue I guess...) I'll not put the code for that but I will give you a hint of a way to do it: substract inside a loop until you have zero leaves.
Here is a recursive way to do it.
private static int[] numberOfLeaves(int year) {
if (year > 1) {
if (year % 3 != 0) {
int[] ret1 = new int[2];
ret1[0] = ++numberOfLeaves(year - 1)[0];
ret1[1] = numberOfLeaves(year - 1)[1] * 2;
return ret1;
} else {
int[] ret2 = new int[2];
ret2[0] = ++numberOfLeaves(year - 1)[0];
ret2[1] = numberOfLeaves(year - 1)[1] * 3;
return ret2;
}
}
int[] ret = new int[2];
ret[0] = year;
ret[1] = year * 2;
return ret;
}
It is tested. When you print out the data, you should access it by index (ret[0] for number of years and ret[1] for number of leaves.).

optimization causes timeout? [duplicate]

This question already has answers here:
Number of consectuive sums error?
(2 answers)
Closed 5 years ago.
I am working on a program that takes an integer and finds the number of combinations of consecutive sums that the integer has:
The number 13 can be expressed as a sum of consecutive positive
integers 6 + 7. Fourteen can be expressed as 2 + 3 + 4 + 5, also a sum
of consecutive positive integers. Some numbers can be expressed as a
sum of consecutive positive integers in more than one way. For
example, 25 is 12 + 13 and is also 3 + 4 + 5 + 6 + 7.
I researched and read that it's the number of odd factors minus one. So I wrote a program that finds the number of odd factors and my answer is still wrong in certain cases. Any insight?
Code seems to work fine but there is a crash due to Timeout which is probably due to optimization error.
The constraints for possible input size is
1 to 10^(12)
static int consecutive(long num) {
while (num % 2 == 0) num /= 2; // 1st opt.
return consecutiveHelper(num)-1;
}
public static int consecutiveHelper(long num) {
long factorNumber = 1;
int count = 0;
while(factorNumber <= num / 2) { // 2nd opt.
if(num % factorNumber == 0) {
count++;
}
factorNumber += 2; // 3rd opt.
}
if (num % 2 != 0) {
count++;
}
return count;
}
Let's try to find a pseudo-optimized method to resolve your problem :
What you need to do is to decompose your number in prime factors.
For example, if you take 1200 :
1200 = 2*2*2*2*3*5*5 = 1 * 2^4 * 3^1 * 5^2
You can then analyze how you could get odd factors with those prime factors. A quick analyze will tell you that :
odd * odd = odd
odd * even = even
even * even = even
With that in mind, let's find all the factors we get with odd * odd :
1 * 1 = 1
3 * 1 = 3
5 * 1 = 5
5 * 3 = 15
5 * 5 = 25
5 * 5 * 3 = 75
A quick way to find these combinations without writing them all is the "plus 1 method" : add 1 to the number of occurences of each prime odd factor, and multiply them together :
We found that 1200 = 1 * 2^4 * 3^1 * 5^2, so we can do :
("number of 3" + 1) ("number of 5" + 1) = (1 + 1) ( 2 + 1) = 6
There are 6 odd factors for the number 1200, and as you stated, remove 1 from that number to get the number of combinations of consecutive sums that 1200 has :
6 - 1 = 5 <-- woohoo ! finally got the result !
Now, let's look at the code. What we want to have is a Map, the keys being the prime factors and the values being the number of their occurences :
/*
If number is odd,
find the number in the keys and add 1 to its value.
If the number is not in the keys, add it with value = 1.
*/
public static void addValue(Map<Integer, Integer> factors, int i) {
if(i % 2 != 0) {
int count = factors.containsKey(i) ? factors.get(i) : 0;
factors.put(i, ++count);
}
}
/*
Classic algorithm to find prime numbers
*/
public static Map<Integer, Integer> oddPrimeFactors(int number) {
int n = number;
Map<Integer, Integer> factors = new HashMap<>();
for (int i = 2; i <= n / i; i++) {
while (n % i == 0) {
addValue(factors, i);
n /= i;
}
}
if(n > 1) addValue(factors, n);
return factors;
}
With that, let's try to print what the map contains for number 1200 :
public static void main(String[] args) {
int n = 1200;
System.out.println(oddPrimeFactors(n));
}
$n : {3=1, 5=2}
Good ! Now let's finish the program with the method we developed before :
public static int combinations = 1;
public static void main(String[] args) {
int n = 1200;
oddPrimeFactors(n).forEach((key, value) -> combinations *= (value + 1));
combinations--;
System.out.println(combinations);
}
$combinations = 5
Finished ! feel free to ask if you did not understand something !
Note : I tried my program with the max value Integer can handle and it took less than one second for my program to proceed, which seems pretty fast to me. It could probably be faster though, it's up to you to find the most optimized version of this code !

How can I make this method end its recursion and reach a maximum?

I ran into a StackOverflowError when running a solution I wrote to an assignment.
These are the exact instructions from the book Java Methods: A & AB:
Write a program in which Cookie Monster finds the optimal path from the upper left corner (0,0) to the lower right corner(SIZE-1,SIZE-1) in a cookie grid (a 2-D array). The elements of the grid contain cookies (a non-negative number) or barrels (-1). On each step, Cookie Monster can only go down or to the right. He is not allowed to step on barrels. The optimal path contains the largest number of cookies.
The program reads the cookie grid from a file and reports the number of cookies on the optimal path. (The path itself is not reported.) A sample data file is provided in JM\Ch19\Exercises\cookies.dat.
Hint: Use a stack. If there is only one way to proceed from the current position, then go there and update the total accumulated number of cookies. If there are two ways to proceed, save one of the possible two points (and its total) on the stack and proceed to the other point. If you have reached the lower-right corner, update the maximum. If there is nowhere to go, examine the stack: pop a saved point, if any, and resume from there.
The goal is to give my teacher the best possible path (the one with the most "cookies" on it).
Okay. so the mentioned cookie map file is this:
1 3 0 5 -1 7 -1 -1 0 4 2 1
-1 3 2 1 -1 4 -1 5 3 -1 1 0
5 4 8 -1 3 2 2 -1 4 -1 0 0
2 1 0 4 1 -1 8 0 2 -1 2 5
1 4 0 1 -1 0 3 2 2 4 1 4
0 1 4 1 1 6 1 4 5 2 1 0
3 2 5 2 0 7 -1 2 1 0 -1 3
0 -1 4 -1 -1 3 5 1 4 2 1 2
5 4 8 -1 3 2 2 -1 4 -1 0 0
2 1 0 4 1 -1 8 0 2 -1 2 5
1 3 0 5 -1 7 -1 -1 0 4 2 1
0 0 3 1 5 2 1 5 4 1 3 3
And this is the class I use to get a 2-D array of the numbers (I know this part works.) Using A BlueJ debugger, the 2-D array seems to be what I want it to be.
import java.util.*;
import java.io.*;
public class MapReader
{
public static int[][] grid;
public static Scanner gridscanner = null;
public static int[][] getMap()
{
File file = new File("cookies.dat");
try
{
gridscanner = new Scanner(file);
}
catch (FileNotFoundException ex)
{
System.out.println("*** Cannot open cookis.dat ***");
System.exit(1);
}
int row = 12;
grid = new int[row][row];
for(int r = 0; r < row; r++)
{
for(int c = 0; c < row; c++)
{
grid[r][c] = gridscanner.nextInt();
}
}
return grid;
}
}
And here is a class I use to keep track of saved positions, their values, and their locations for when I'm traversing this "cookie map":
import java.util.*;
public class Point
{
int row;
int col;
int total;
public Point(int r, int c, int t)
{
row = r;
col = c;
total = t;
}
public int getRow() { return row; }
public int getCol() { return col; }
public int getValue() { return MapReader.getMap()[row][col]; }
public int getTotal() { return total; }
}
And finally, here is the class that I use to recursively travel through the 2D array. You'll notice that I prefer to go right when two paths are available but then go down when I pop a Point from the "saved" Stack. The problem lies in this class as far as I know: How can I make the method end its recursion and reach a maximum?
import java.util.*;
public class CookieMonster
{
private static int[][] map = MapReader.getMap();
private static int max = 11;
private static int total, maximum;
private static Stack<Point> saved = new Stack<Point>();
public static void main(String[] args)
{
System.out.println(move(0,0));
}
public static int move(int r, int c)
{
int right = 0;
int down = 0;
boolean isright = true;
boolean isdown = true;
if (c < max)
{
right = map[r][c + 1];
}
else
isright = false;
if (r < max)
{
down = map[r + 1][c];
}
else
isdown = false;
if (right == -1)
isright = false;
if (down == -1)
isdown = false;
if (isright && isdown)
{
saved.push(new Point(r + 1, c, total + down));
total += right;
move(r, c + 1);
}
else if (isright)
{
total += right;
move(r, c + 1);
}
else if (isdown)
{
total += down;
move(r + 1, c);
}
else
{
if (r == max && c == max)
{
if (maximum < total)
maximum = total;
}
if (!saved.isEmpty())
{
Point sd = saved.pop();
total = sd.getTotal();
move(sd.getRow(), sd.getCol());
}
}
return maximum;
}
}
I know the hint suggests to use a stack, but this problem can be solved much more efficiently using dynamic programming. It is basically recursion with a memory of previously visited paths to avoid recomputation.
Assuming you index the matrix starting at 1, Your cost function should be as follows:
c(i, j) = -INF if i == 0 or j == 0 or data(i, j) < 0
data(1, 1) if i == 1 and j == 1
data(i, j) + min(c(i, j - 1), c(i - 1, j))
You can iterate in the usual nested i-j loop from left to right and up to down.
c(n, n) will give you the result of the optimal path.
This seems np-complete. Using a stack and writing the logic to return to a former path if you run into a dead-end seems like wasted effort. You are going to have to use a lot of brute force even with the stack and logic. It seems easier to just use a primitive to store the number of cookies and just write some logic to move down and right at random. If you hit a dead end, just throw that result out and start over. If you hit the end, save that value and check to see if it is larger than a previous path. It if it is, keep it until you find a larger one. If you run it enough times, you will find the best path. I can't imagine it would take more than a few seconds to find the most cookies.

Categories

Resources