Question:
In this problem, the scenario we are evaluating is the following: You're standing at the base of a staircase and are heading to the top. A small stride will move up one stair, and a large stride advances two. You want to count the number of ways to climb the entire staircase based on different combinations of large and small strides. For example, a staircase of three steps can be climbed in three different ways: three small strides, one small stride followed by one large stride, or one large followed by one small.
The call of waysToClimb(3) should produce the following output:
1 1 1,
1 2,
2 1
My code:
public static void waysToClimb(int n){
if(n == 0)
System.out.print("");
else if(n == 1)
System.out.print("1");
else {
System.out.print("1 ");
waysToClimb(n - 1);
System.out.print(",");
System.out.print("2 ");
waysToClimb(n - 2);
}
}
My output:
1 1 1,
2,
2 1
My recursion doesn't seem to remember the path it took any idea how to fix it?
Edit:
Thank you guys for the responses. Sorry for the late reply
I figured it out
public static void waysToClimb(int n){
String s ="[";
int p=0;
com(s,p,n);
}
public static void com(String s,int p,int n){
if(n==0 && p==2)
System.out.print(s.substring(0,s.length()-2)+"]");
else if(n==0 && p !=0)
System.out.print(s+"");
else if(n==0 && p==0)
System.out.print("");
else if(n==1)
System.out.print(s+"1]");
else {
com(s+"1, ",1,n-1);
System.out.println();
com(s+"2, ",2,n-2);
}
}
If you explicity want to print all paths (different than counting them or finding a specific one), you need to store them all the way down to 0.
public static void waysToClimb(int n, List<Integer> path)
{
if (n == 0)
{
// print whole path
for (Integer i: path)
{
System.out.print(i + " ");
}
System.out.println();
}
else if (n == 1)
{
List<Integer> newPath = new ArrayList<Integer>(path);
newPath.add(1);
waysToClimb(n-1, newPath);
}
else if (n > 1)
{
List<Integer> newPath1 = new ArrayList<Integer>(path);
newPath1.add(1);
waysToClimb(n-1, newPath1);
List<Integer> newPath2 = new ArrayList<Integer>(path);
newPath2.add(2);
waysToClimb(n-2, newPath2);
}
}
initial call: waysToClimb(5, new ArrayList<Integer>());
Below mentioned solution will work similar to Depth First Search, it will explore one path. Once a path is completed, it will backtrace and explore other paths:
public class Demo {
private static LinkedList<Integer> ll = new LinkedList<Integer>(){{ add(1);add(2);}};
public static void main(String args[]) {
waysToClimb(4, "");
}
public static void waysToClimb(int n, String res) {
if (ll.peek() > n)
System.out.println(res);
else {
for (Integer elem : ll) {
if(n-elem >= 0)
waysToClimb(n - elem, res + String.valueOf(elem) + " ");
}
}
}
}
public class Test2 {
public int climbStairs(int n) {
// List of lists to store all the combinations
List<List<Integer>> ans = new ArrayList<List<Integer>>();
// initially, sending in an empty list that will store the first combination
csHelper(n, new ArrayList<Integer>(), ans);
// a helper method to print list of lists
print2dList(ans);
return ans.size();
}
private void csHelper(int n, List<Integer> l, List<List<Integer>> ans) {
// if there are no more stairs to climb, add the current combination to ans list
if(n == 0) {
ans.add(new ArrayList<Integer>(l));
}
// a necessary check that prevent user at (n-1)th stair to climb using 2 stairs
if(n < 0) {
return;
}
int currStep = 0;
// i varies from 1 to 2 as we have 2 choices i.e. to either climb using 1 or 2 steps
for(int i = 1; i <= 2; i++) {
// climbing using step 1 when i = 1 and using 2 when i = 2
currStep += 1;
// adding current step to the arraylist(check parameter of this method)
l.add(currStep);
// make a recursive call with less number of stairs left to climb
csHelper(n - currStep, l, ans);
l.remove(l.size() - 1);
}
}
private void print2dList(List<List<Integer>> ans) {
for (int i = 0; i < ans.size(); i++) {
for (int j = 0; j < ans.get(i).size(); j++) {
System.out.print(ans.get(i).get(j) + " ");
}
System.out.println();
}
}
public static void main(String[] args) {
Test2 t = new Test2();
t.climbStairs(3);
}
}
Please note this solution will timeout for larger inputs as this isn't a memoized recursive solution and can throw MLE(as I create a new list when a combination is found).
Hope this helps.
if anyone looking for a python solution, for this problem.
def way_to_climb(n, path=None, val=None):
path = [] if path is None else path
val = [] if val is None else val
if n==0:
val.append(path)
elif n==1:
new_path = path.copy()
new_path.append(1)
way_to_climb(n-1, new_path, val)
elif n>1:
new_path1 = path.copy()
new_path1.append(1)
way_to_climb(n-1, new_path1, val)
new_path2 = path.copy()
new_path2.append(2)
way_to_climb(n-2, new_path2, val)
return val
Note: it is based on the #unlut solution, here OP has used a top-down recursive approach. This solution is for all people who looking for all combination of staircase problem in python, no python question for this so i have added a python solution here
if we use a bottom-up approach and use memorization, then we can solve the problem faster.
Even though you did find the correct answer to the problem with your code, you can still improve upon it by using just one if to check if the steps left is 0. I used a switch to check the amount of steps taken because there are only 3 options, 0, 1, or 2. I also renamed the variables that were used to make the code more understandable to anyone seeing it for the first time, as it is quite confusing if you are just using one letter variable names. Even with all these changes the codes run the same, I just thought it might be better to add some of these things for others who might view this question in the future.
public static void climbStairsHelper(String pathStr, int stepsTaken, int stepsLeft)
{
if(stepsLeft == 0)
{
switch(stepsTaken)
{
case 2:
System.out.print(pathStr.substring(0, pathStr.length() - 2) + "]");
break;
case 1:
System.out.print(pathStr + "");
break;
case 0:
System.out.print("");
break;
}
}
else if(stepsLeft == 1)
{
System.out.print(pathStr + "1]");
}
else
{
climbStairsHelper(pathStr + "1, ", 1, stepsLeft - 1);
System.out.println();
climbStairsHelper(pathStr + "2, ", 2, stepsLeft - 2);
}
}`
`
Related
I'm trying to implement the algorithm to solve Project Euler Problem #14, which asks to find a number in a given range that outputs the largest Collatz conjecture sequence length. My code is below:
import java.util.ArrayList;
class Collatz {
private static ArrayList<ArrayList<Long>> previousNums = new ArrayList();
public static int seqLen(int x) {
ArrayList<Long> colSeq = new ArrayList();
long val = x;
colSeq.add(val);
while (val > 1) {
if (val%2 == 0) {
val/=2;
if (val < previousNums.size()) /*used to check if index exists*/{
colSeq.addAll(previousNums.get((int)val));
break;
}
else colSeq.add(val);
}
else {
val = 3*val + 1;
if (val < previousNums.size()) {
colSeq.addAll(previousNums.get((int)val));
break;
}
else colSeq.add(val);
}
}
previousNums.add(colSeq);
return colSeq.size();
}
public static void main(String[] args) {
int greatestNum = 0;
long totalVal = 0;
for (int i = 0; i<=1000000; i++) {
int collatz = seqLen(i);
if (collatz > totalVal) {}
greatestNum = i;
totalVal = collatz;
}
System.out.println(greatestNum + " " + totalVal);
}
}
The output I get is
1000000 153
While this is not the correct answer, 153 is the correct sequence length for 1 million. Based off of this, I could assume that my Collatz conjecture algorithm works, but not the comparison part. However, I can't really find anywhere else I could modify the code. Any ideas? Thank you and please pardon the possibility of this being a duplicate (not many other posts had the same problem).
Wow, a mere syntax error was the issue. Looks like I didn't pay attention to:
if (collatz > totalVal) {}
greatestNum = i;
totalVal = collatz;
Yup, didn't enclose the code with the braces.
I need help to design java code for generating bit array for any given integer in following manner:
23 should produce output as 1101011 (min length array)
explaination :
positions are given as 1 -2 4 -8 16 -32 ....
So 1101011 can be evaluated as:
1*1 + 1*-2 + 0*4+ 1*-8 + 0*16 +1*-32 + 1*64 = 23
This is the so-called negabinary representation of numbers (described first by Vittorio Grünwald in 1885). They can be encoded in a fashion very similar to the usual binary representation, just working with -2 instead of 2 as base (Java code inspired by C# code on https://en.wikipedia.org/wiki/Negative_base ):
class EncodeNegaBinary {
public static void main(String[] args) {
int n=0,input=0;
String result="";
final String[] BITS = { "0","1" };
if (args.length != 1) {
System.err.println("Please enter an integer to be converted");
return;
} else {
input = n = Integer.parseInt(args[0]);
}
while (n != 0) {
int r = n%-2;
n /= -2;
if (r == -1) {
r=1;
n++;
}
result = BITS[r] + result;
}
System.out.printf( "%d -> %s\n", input, result);
}
}
Since it is not usual int to binary conversion, at each step we need to consider two cases as at each position there can be only two choices 0 or 1. This is done recursively in the below program:
public class ModifiedIntToBinaryConversion{
public static int calcBinaryString(int reqSum, int currSum, int add, String bs) {
if (reqSum == currSum) { // base condtion 1
System.out.println("The string is \n" + bs);
return currSum;
}
if (add + currSum > reqSum) { // base condtion 2
return 0;
}
int newAdd = add * -2;
// System.out.println("new add is "+ newAdd +" currSum is "+ currSum);
int s1 = calcBinaryString(reqSum, currSum + add, newAdd, bs + "1");
if (s1 == reqSum)
return s1;
int s2 = calcBinaryString(reqSum, currSum, newAdd, bs + "0");
return s2;
}
public static void calcBinaryString(int sum) {
int s1 = calcBinaryString(sum, 0, 1, "");
if(s1 != sum) {
System.out.println("The binary equivalent couldn't be found");
}
}
public static void main(String[] args) {
calcBinaryString(23);
}
}
Now base condition 1 is clear as I am just checking whether required sum and calculated sum are equal.
For base condition 2, I will accept it's result of debugging and a bit of thought as I was getting Stackoverflow errors. Once the calculated sum becomes greater than the required sum and then we take the next -ve number so that it become less than req. sum. But then the next +ve number will be greater than the -ve number we just considered and thus the chances are very less that the calculated sum will ever be equal to req. sum.
I am working on a problem from Cracking the Coding Interview, problem 9.6 page 110.
Here is the problem:
Implement an algorithm to print all valid (e.g., properly opened and closed combinations of n-pairs of parentheses. Examples
b(1) - "()"
b(2) - "(()), ()()"
b(3) - "((())), (()()), (())(), ()(()), ()()()"
I am trying to use the bottom up recursion approach that the author discusses on page 107 - "We start with knowing how to solve the problem for a simple case, like a list with only one element, and figure out how to solve the problem for two elements, then for three elements, and so on. The key here is to think about how you can build the solution for one case off the previous case"
Here is the code I have so far
static void print(int n) {
print(n, new HashSet<String>(), "", "");
}
static void print(int n, Set<String> combs, String start, String end) {
if(n == 0) {
if(!combs.contains(start + end)) {
System.out.print(start + end);
combs.add(start + end);
}
} else {
print(n-1, combs, "(" + start, end +")");
System.out.print(", ");
print(n-1, combs, start, end + "()");
System.out.print(", ");
print(n-1, combs, "()" + start, end);
}
}
To get this code, I worked from the first case to the second case. I saw that b(2) = "(b(1)), b(1),b(1)"
This code does work for the first two cases. I am really struggling with the third case though. Can someone give me a hint(not the whole answer, could turn to the back of the book for that), about how to go from case 2 to case 3, or in other words using case 2 to get to case 3? Like how would you go from (()), ()() to ((())), (()()), (())(), ()(()), ()()()? Would you abandon the pattern you saw from b(1) to b(2) because it doesn't work for b(2) to b(3)?
We can generate from b(n) to b(n + 1) by using this recursive formula:
(b(n - x))b(x) with 0 <= x <= n
So, you can have all of your combinations by iterating through all x.
Code:
public static ArrayList<String> cal(int num){
if(num == 0){
ArrayList<String> list = new ArrayList();
list.add("");
return list;
}else{
ArrayList<String>result = new ArrayList();
for(int i = 0; i <= num - 1; i++){
ArrayList<String> a = cal(i);
ArrayList<String> b = cal(num - 1 - i);
for(String x : a){
for(String y : b){
result.add("(" + x + ")" + y);
}
}
}
return result;
}
}
Input: 3
Output: ()()(), ()(()), (())(), (()()), ((()))
Input: 4
Output: ()()()(), ()()(()), ()(())(), ()(()()), ()((())), (())()(), (())(()), (()())(), ((()))(), (()()()), (()(())), ((())()), ((()())), (((())))
Thanks Khanna111 for pointing out the mistake I made in my original answer, which was incomplete and under-counted the string patterns. As a result, I have updated my answer accordingly.
Please consider giving credit to Pham Trung for his answer with the correct recursive formula. My answer is essentially the same as his, with only a slight difference in the way I formulate the construction of patterns from smaller sub-problems (as I find it easier to explain the details in my approach).
========================================================================
Update Solution
For any valid pattern s of size n, s falls in exactly one of the following cases:
Case 1: s cannot be partitioned into two valid patterns of smaller size
Case 2: s can be partitioned into two valid patterns of smaller size
For case 1, s must be of the form (_____), where _____ is a valid pattern of size n - 1. So in this case, for every valid pattern t of size n - 1, we simply construct a pattern s by concatenating t with ( and ) as prefix and suffix, respectively (i.e. s = (t)).
For case 2, we can partition s into uv, where u and v are both valid patterns of smaller size. In this case, we have to consider all possible patterns of u and v, where u can be any valid pattern of size i = 1, 2, ..., n - 1, while v can be any valid pattern of size n - i.
When n = 0, clearly only the empty string is a valid pattern, so we have dp(0) = { "" } as our base case. A complete implementation with caching to improve the performance is given below:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class BalancingBrackets {
private static Map<Integer, Set<String>> dp = new HashMap<>();
public static void main(String[] args) {
Set<String> result = compute(4);
boolean isFirst = true;
for (String s : result) {
if (isFirst) {
isFirst = false;
System.out.print(s);
} else {
System.out.print(", " + s);
}
}
}
private static Set<String> compute(Integer n) {
// Return the cached result if available
if (dp.containsKey(n)) {
return dp.get(n);
}
Set<String> set = new HashSet<>();
if (n == 0) {
// This is the base case with n = 0, which consists only of the
// empty string
set.add("");
} else if (n > 0) {
// For generating patterns in case 1
for (String s : compute(n - 1)) {
set.add("(" + s + ")");
}
// For generating patterns in case 2
for (int i = 1; i < n; i++) {
Set<String> leftPatterns = compute(i);
Set<String> rightPatterns = compute(n - i);
for (String l : leftPatterns) {
for (String r : rightPatterns) {
set.add(l + r);
}
}
}
} else {
// Input cannot be negative
throw new IllegalArgumentException("Input cannot be negative.");
}
// Cache the solution to save time for computing large size problems
dp.put(n, set);
return set;
}
}
I'm trying to use a Sieve of Eratosthenes method for finding the largest prime factor of a large number (problem 3 in Project Euler).
My syntax seems to be correct, and i am using Long (not int), but I'm getting the following error message:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index: 1, Size: 1
at java.util.ArrayList.rangeCheck(Unknown Source)
at java.util.ArrayList.get(Unknown Source)
at problem3.ProblemThree.Factor(ProblemThree.java:49)
at problem3.ProblemThree.Recursion(ProblemThree.java:37)
at problem3.ProblemThree.main(ProblemThree.java:83)
I don't know why this is happening. Could somebody please tell me what I'm doing wrong here?
package problem3;
import java.util.List;
import java.util.ArrayList;
public class ProblemThree
{
//initializing variables and lists
long factorNo;
long nowTesting;
int i;
List<Long> allPrimeList = new ArrayList<Long>();
List<Long> ourPrimes = new ArrayList<Long>();
ProblemThree(long x) //constructor; the input "x" is the number whose highest prime factor is being sought
{
factorNo = x;
}
void initialize() //use the workaround initialization (add 2 to the allPrimesList, set nowTesting to 3).
//If the factorNo is even, add 2 to the primes list
//TODO: need more elegant solution
{
allPrimeList.add((long) 2);
nowTesting=3;
if(factorNo % 2 == 0) ourPrimes.add((long) 2);
i = 0;
}
void recursion() //keep factoring the next nowTesting until the next nowTesting is greater than half of the factorNo
{
while (nowTesting <= (factorNo/2))
{
nowTesting = factor(nowTesting);
}
System.out.println(ourPrimes);
}
long factor(long t) //The factorization algorithm. Lists all the factors of long t
{
nowTesting = t;
// Line 49:
if ((nowTesting % allPrimeList.get(i)) == 0)
{
i = 0;
return (nowTesting + 2);
}
else
if(i <= allPrimeList.size()) //if we have not yet reached the end of ourPrimeList
{
i++;
return nowTesting;
}
else //if the end of ourPrimeList has been reached without a single modulus==0, this number is a prime
{
allPrimeList.add(nowTesting);
if(factorNo%nowTesting==0) //if the nowTesting is a prime factor of factorNo, it will be perfectly divisible
{
ourPrimes.add(nowTesting);
}
i=0;
return (nowTesting+2);
}
}
public static void main (String[] args)
{
ProblemThree pt = new ProblemThree(600851475143L);
pt.initialize();
pt.recursion();
}
}
thank you everyone for patiently wading through my code, I realize that it must have been excruciatingly painful :)
I have just solved the problem. My previous approach seems very complicated in retrospect. This is the final solution I used, quite a bit more elegant, although it still has room for improvement:
//second attempt from the ground up!
package problem3;
public class BiggestPrime
{
long lInput;
long factorTest;
long currentHeight;
boolean divided;
public BiggestPrime(long n)
{
factorTest = 2;
currentHeight = n;
System.out.println("The prime factors of " + n + " are:");
while (factorTest<currentHeight)
{
if (divided == true) {factorTest = 2; divided = false;}
if (factorTest > currentHeight) {System.out.println("factorTest is greater than currentHeight; breaking"); break;}
if (currentHeight%factorTest==0)
{
System.out.println(factorTest);
currentHeight /= factorTest;
divided = true;
}
else { factorTest = factorTest + 1L; divided = false;}
}
if (factorTest == currentHeight)
{
System.out.println(factorTest);
}
System.out.println("The end");
}
public static void main (String[] args)
{
BiggestPrime bp = new BiggestPrime(600851475143L);
}
}
An interesting approach. Of course, nobody should solve your Euler challenges. But did you know that the second time, you enter 'factor' nowTesting is 3?
// The factorization algorithm. Lists all the factors of long t
long factor (final long nowTesting)
{
System.out.println ("entering factor: " + nowTesting);
Minor ideas:
allPrimeList.add ((long) 2);
can be written:
allPrimeList.add (2L);
and you pobably recognized the "final" in front of the 'long' parameter in factor? It helps reasoning about code, if you mark everything which isn't changed final. In practise, the consequence is, that your Javacode is cluttered with 'final' modifiers, but that's how it is. It's a sign of good code - maybe not of good design. Final could have been the default.
At line 49, shouldn't you be checking if nowTesting is divisible by i, not the ith element of allPrimes?
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);
}
}
}
}