1

For any given value N we have to find the number of ways to reach the top while using steps of 1,2 or 3 but we can use 3 steps only once. for example if n=7 then possible ways could be

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

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

etc but we cannot have [3,3,1] or [1,3,3]

I have managed to solve the general case without the constraint of using 3 only once with dynamic programming as it forms a sort of fibonacci series

 def countWays(n) : 
    res = [0] * (n + 1) 
    res[0] = 1
    res[1] = 1
    res[2] = 2

    for i in range(3, n + 1) : 
        res[i] = res[i - 1] + res[i - 2] + res[i - 3] 

    return res[n] 

how do I figure out the rest of it?

Guy Coder
  • 24,501
  • 8
  • 71
  • 136
aditya singh
  • 111
  • 2
  • 10

2 Answers2

1

Let res0[n] be the number of ways to reach n steps without using a 3-step, and let res1[n] be the number of ways to reach n steps after having used a 3-step.

res0[i] and res1[i] are easily calculated from the previous values, in a manner similar to your existing code.

This is an example of a pretty common technique that is often called "graph layering". See, for example: Shortest path in a maze with health loss

Matt Timmermans
  • 53,709
  • 3
  • 46
  • 87
  • I'm not sure that is sufficient, since you do not per se first use a 3-step. You thus need to find out *per* stair how many steps there were, and thus multiply with that number, since you can insert the 3-step everywhere in the stair. – Willem Van Onsem Aug 17 '19 at 12:23
  • I didn't say you had to use the 3-step *first*. `res1[i] = res0[i-3] + res1[i-2] + res1[i-1]`. The first term represents using the 3-step from `i-3` to `i`. – Matt Timmermans Aug 17 '19 at 12:25
  • @WillemVanOnsem the recurrence Matt Timmermans shared, `res1[i] = res0[i-3] + res1[i-2] + res1[i-1]`, returns the same results as your function. Please consider voting up an answer that's teaching something new :) – גלעד ברקן Aug 17 '19 at 15:41
0

Let us first ignore the three steps here. Imagine that we can only use steps of one and two. Then that means that for a given number n. We know that we can solve this with n steps of 1 (one solution), or n-2 steps of 1 and one step of 2 (n-1 solutions); or with n-4 steps of 1 and two steps of 2, which has n-2×n-3/2 solutions, and so on.

The number of ways to do that is related to the Fibonacci sequence. It is clear that the number of ways to construct 0 is one: just the empty list []. It is furthermore clear that the number of ways to construct 1 is one as well: a list [1]. Now we can proof that the number of ways Wn to construct n is the sum of the ways Wn-1 to construct n-1 plus the number of ways Wn-2 to construct n-2. The proof is that we can add a one at the end for each way to construct n-1, and we can add 2 at the end to construct n-2. There are no other options, since otherwise we would introduce duplicates.

The number of ways Wn is thus the same as the Fibonacci number Fn+1 of n+1. We can thus implement a Fibonacci function with caching like:

cache = [0, 1, 1, 2]
def fib(n):
    for i in range(len(cache), n+1):
        cache.append(cache[i-2] + cache[i-1])
    return cache[n]

So now how can we fix this for a given step of three? We can here use a divide and conquer method. We know that if we use a step of three, it means that we have:

1 2 1 … 1 2 3 2 1 2 2 1 2 … 1
\____ ____/   \_______ _____/
     v                v
  sum is m    sum is n-m-3

So we can iterate over m, and each time multiply the number of ways to construct the left part (fib(m+1)) and the right part (fib(n-m-3+1)) we here can range with m from 0 to n-3 (both inclusive):

def count_ways(n):
    total = 0
    for m in range(0, n-2):
        total += fib(m+1) * fib(n-m-2)
    return total + fib(n+1)

or more compact:

def count_ways(n):
    return fib(n+1) + sum(fib(m+1) * fib(n-m-2) for m in range(0, n-2))

This gives us:

>>> count_ways(0)  # ()
1
>>> count_ways(1)  # (1)
1
>>> count_ways(2)  # (2) (1 1)
2
>>> count_ways(3)  # (3) (2 1) (1 2) (1 1 1)
4
>>> count_ways(4)  # (3 1) (1 3) (2 2) (2 1 1) (1 2 1) (1 1 2) (1 1 1 1)
7
Willem Van Onsem
  • 443,496
  • 30
  • 428
  • 555