Search code examples
algorithmrecursionbacktrackingrecursive-backtracking

backtracking n staircases at most k steps in a single jump


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?


Solution

  • 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.