2

You need to climb a staircase that has n steps, and you decide to get some extra exercise by jumping up the steps. You can cover at most k steps in a single jump. Return all the possible sequences of jumps that you could take to climb the staircase, sorted.

My implementation is obviously giving me the wrong answer.

def climbingStaircase(n, k):
    final_res=[]
    final_res.append(CSR(n,k,[]))
    return final_res

def CSR(n,k,res):
    if n == 0:
        return res        
    else:
        for i in range(1,k+1):
            if n-i>=0:
                res.append(i)
                n=n-i
                res=CSR(n,i,res)
        return res

For n = 4 and k = 2, the output should be

[[1, 1, 1, 1],
 [1, 1, 2],
 [1, 2, 1],
 [2, 1, 1],
 [2, 2]]

Actual output:

[[1,1,1,1,2,1]]

Can someone point out which part I'm missing?

aerin
  • 20,607
  • 28
  • 102
  • 140

4 Answers4

7

One huge problem is in the code below: you deduct the quantity of steps for each possibility within the step range.

n=n-i
res=CSR(n,i,res)

When you're done exploring what you can do with a 1-step jump, you need to backtrack and try from the same starting point (this instance's original value of n) with a 2-step jump. Change the code to:

res = CSR(n-i, i, res)

This keeps the n value intact as you go through the loop.

In addition, you can't limit future jumps to the max of what you just took. Change that second parameter, too:

res = CSR(n-i, k, res)

That should get you moving. Also try this lovely debug blog for help. At least insert one or two tracing statements, such as

print n, k, res

at the top of your routine.

CAVEAT

This is not all of your trouble. The largest remaining problem is that CSR returns only one solution: every step you take is appended to the same list. You need a way to gather the completed solutions as separate lists; the append in climbingStaircase is executed only once, after CSR is entirely finished.

You need to recognize a completed solution at n==0.

DEBUGGING HELP

Here is a version of your program with the recursion parameters fixed, and debugging traces inserted.

indent = ""

def climbingStaircase(n, k):
    final_res = []
    final_res.append(CSR(n, k, []))
    return final_res

def CSR(n, k, res):
    global indent
    indent += "  "
    print indent, n, k, res
    if n == 0:
        print "SOLUTION", res
    else:
        for i in range(1, k+1):
            if n-i >= 0:
                CSR(n-i, k, res + [i])
    indent = indent[:-2]

print climbingStaircase(4, 2)

Note the use of "indent" to help visualize your recursion and backtracking. The critical part here is that, instead of updating res globally, I've left it as a local variable. I've also removed the return value for now, simply dumping to output the solutions as they're found. You can see how it works:

   4 2 []
     3 2 [1]
       2 2 [1, 1]
         1 2 [1, 1, 1]
           0 2 [1, 1, 1, 1]
SOLUTION [1, 1, 1, 1]
         0 2 [1, 1, 2]
SOLUTION [1, 1, 2]
       1 2 [1, 2]
         0 2 [1, 2, 1]
SOLUTION [1, 2, 1]
     2 2 [2]
       1 2 [2, 1]
         0 2 [2, 1, 1]
SOLUTION [2, 1, 1]
       0 2 [2, 2]
SOLUTION [2, 2]
[None]

With this stuff in place, I'm hopeful you can trace your logic and figure out how to capture the sequence of solutions at a level of your choosing.

Prune
  • 76,765
  • 14
  • 60
  • 81
  • Hi @Prune thanks for your fast answer! isn't "if n == 0: return res " in CSR recognizing a complete solution? Yes I do get one big list, not the list of list. I tried to pop the last items that I added but no success yet. – aerin Jul 26 '17 at 22:05
  • That does recognize a solution, but then you mis-handle it. You pass it back to the previous instance level, save it over itself, and then go to the next jump size in the allowed range, without saving the completed solution in the master list. You need to re-think your logic in this branch of the problem: append the completed solution and reset the partial solution to the previous step level. – Prune Jul 26 '17 at 22:09
  • Thank you so much for your time. This is probably the most helpful + considerate answer that I received in SO. – aerin Jul 27 '17 at 01:40
2

Successfully implemented Prune's answer.

def climbingStaircase(n, k):
    res=[]
    CSR(n,k,[],res)
    return res

def CSR(n,k,str_, res):
    if n == 0:
        res.append(str_)
    else:
        for i in range(1,k+1):
            if n-i>=0:
                CSR(n-i,k,str_+[i],res)
aerin
  • 20,607
  • 28
  • 102
  • 140
1

A quick Java version of this solution:

int[][] climbingStaircase(int n, int k) {
    List<ArrayList<Integer>> list = new ArrayList<>();
    climb(n, k, new ArrayList<Integer>(), list);

    // convert to int[][]
    int[][] result = new int[list.size()][];
    for (int i=0; i<list.size(); i++) {
        List<Integer> l = list.get(i); 
        int [] arr = new int[l.size()];
        for (int j=0; j<l.size(); j++)
            arr[j] = l.get(j);
        result[i] = arr;
    }
    return result;
}
void climb(int n, int k, ArrayList<Integer> prev, List<ArrayList<Integer>> list) {
    if (n==0) { // no more stairs, done climbing
        list.add(prev);
    } else {
        for (int i=1; i<=k; i++) { // climb remaining stairs in intervals from 1 to k steps
            if (i <= n) { // no need to test intervals larger than remaining # of stairs
                ArrayList<Integer> branch = new ArrayList<>(prev);
                branch.add(i);
                climb(n-i, k, branch, list);
            }
        }
    }
}
0

In Swift 5.5

func solution(n: Int, k: Int) -> [[Int]] {
    var res_final = [[Int]]()
    SRC(n: n, k: k, res: [], &res_final)
    return res_final
}

var indent: String = ""

func SRC(n: Int, k: Int, res: [Int], _ res_final: inout [[Int]]) {
    indent += " "
    print(indent, n, k, res)
    if n == .zero {
        res_final.append(res)
        print("Solution", res)
    } else {
        for i in 1...k {
            if n-i >= .zero {
                SRC(n: n-i, k: k, res: res + [i], &res_final)
            }
        }
    }
    indent = "  "
}
solution(n: 4, k: 2)

MaatheusGois
  • 139
  • 5