Wednesday, 15 October 2014

Solution to Codility Lesson 11: Ladder

The Question:


You have to climb up a ladder. The ladder has exactly N rungs, numbered from 1 to N. With each step, you can ascend by one or two rungs. More precisely:
  • with your first step you can stand on rung 1 or 2,
  • if you are on rung K, you can move to rungs K + 1 or K + 2,
  • finally you have to stand on rung N.
Your task is to count the number of different ways of climbing to the top of the ladder.
For example, given N = 4, you have five different ways of climbing, ascending by:
  • 1, 1, 1 and 1 rung,
  • 1, 1 and 2 rungs,
  • 1, 2 and 1 rung,
  • 2, 1 and 1 rungs, and
  • 2 and 2 rungs.
Given N = 5, you have eight different ways of climbing, ascending by:
  • 1, 1, 1, 1 and 1 rung,
  • 1, 1, 1 and 2 rungs,
  • 1, 1, 2 and 1 rung,
  • 1, 2, 1 and 1 rung,
  • 1, 2 and 2 rungs,
  • 2, 1, 1 and 1 rungs,
  • 2, 1 and 2 rungs, and
  • 2, 2 and 1 rung.
The number of different ways can be very large, so it is sufficient to return the result modulo 2P, for a given integer P.
Write a function:
class Solution { public int[] solution(int[] A, int[] B); }
that, given two non-empty zero-indexed arrays A and B of L integers, returns an array consisting of L integers specifying the consecutive answers; position I should contain the number of different ways of climbing the ladder with A[I] rungs modulo 2B[I].
For example, given L = 5 and:
    A[0] = 4   B[0] = 3
    A[1] = 4   B[1] = 2
    A[2] = 5   B[2] = 4
    A[3] = 5   B[3] = 3
    A[4] = 1   B[4] = 1
the function should return the sequence [5, 1, 8, 0, 1], as explained above.
Assume that:
  • L is an integer within the range [1..30,000];
  • each element of array A is an integer within the range [1..L];
  • each element of array B is an integer within the range [1..30].
Complexity:
  • expected worst-case time complexity is O(L);
  • expected worst-case space complexity is O(L), beyond input storage (not counting the storage required for input arguments).
Elements of input arrays can be modified.

The Solution


The key here is to notice that the number of ways of ascending for N=4 is Fibonacci(N+1).

I created a cache of the first x fibonacci numbers modulo 2^y where x is the max value in array a and y is the max value in array b. 

Then, for every earlier fibonacci number f (f <= x) you can look up in the cache and take cache[f] and modulo it again by whatever value is in b. 

So for example, if we consider the first few fibonacci numbers and cache them modulo 2^3:

Fib(index) =                                            1, 1, 2, 3, 5, 8, 13, 21
index =                                                   0, 1, 2, 3, 4, 5,  6,  7 
cache value = Fib(index) % 8 =             1, 1, 2, 3, 5, 0,  5,  5

Note that in this example, array b will contain values in the range (1, 3).

So we iterate over array a, look up the corresponding value in the cache and take it modulo corresponding value in b. 

Happy days.

Solution is here: 






7 comments:

  1. I got your point of taking max but , tell me why you take max of second array b

    ReplyDelete
  2. Ok, i got the idea of creating a cache table by taking modulus of 2^YMax , i tried your same program by removing 2^ Ymax from the function and it failed in codility test (for small_random correctness) can you please clear my doubt

    ReplyDelete
    Replies
    1. it's a space optimization. you could use long[] to store your cache to avoid this manipulation. it actually masks useful part of fibonacci number as they can become quite big. masks it so it can fit into int (as elements in B are limited to 30)

      Delete
    2. Hi..

      Can you please explain me how did you figure out that we have to select Max(B) for optimization..

      If the question was to represent answers a Fib(A[i]] % B[i] instead of Fib(A[i]] % 2^B[i].


      Thanks

      Delete
  3. Hello, Sorry i might be asking very naive question. But i didn't understand the logic that one could ascend to Nth rung by Fibonacci(N+1) ways.
    I could notice it by examples but i don't exactly understand the logic.
    Could you please help me understand the same.

    ReplyDelete
    Replies
    1. let's say the function is named X. best explanation is to imagine how you're gonna climb down. you can climb 1 step or 2 steps down. if you climb 1 down you have X(N-1) options to climb down to the ground, and if you climb 2 steps down, you have X(N-2) options. together X(N-1) + X(N-2). which is Fibonacci's function :)

      Delete
  4. Hi everyone,
    Can somebody explain why has been created a cache?
    Thank you.

    ReplyDelete

Scala with Cats: Answers to revision questions

I'm studying the 'Scala with Cats' book. I want the information to stick so I am applying a technique from 'Ultralearning...