I just come across a challenging problem (from programming competition practice) that contain recursive sequence as following
given 3 numbers m n k find element a[k] where
a[0] = m
a[1] = n
a[i] = a[i-1] + a[i-2] ; if floor(i/2) mod 2 = 1
a[i] = a[i-1] - a[i-4] ; if floor(i/2) mod 2 = 0
example case: for m=2 n=3 k=6 answer would be 9
a[0] = 2
a[1] = 3
a[2] = 3 + 2 = 5
a[3] = 5 + 3 = 8
a[4] = 8 - 2 = 6
a[5] = 6 - 3 = 3
a[6] = 3 + 6 = 9
...
this is how I generate the sequence (which obviously consume lots of stack and super slow even for the first 100 element)
1 fbm :: Int → Int → Int → Int
2 fbm m n 0 = m
3 fbm m n 1 = n
4 fbm m n x = let a = fbm m n (x-1)
5 b = fbm m n (x-2)
6 c = fbm m n (x-4)
7 in case (x `div` 2) `mod` 2 of
8 1 → a + b
9 0 → a - c
10
11 fbs m n = map (λx→fbm m n x) [0..]
Since the problem required to find element at big (~1000+) index. I try to do a different approach by trying to limit computation only on function with 4 inputs and apply the function with 4 element window recursively on the list but can’t success implementing any of them (something mean I can’t figured out how to do it)
fs1 = map fst $ iterate next (a,b)
where next (a,b) = something
fs2 = m:n:scanl (gen) 2 fs2
where gen [a,b,c,d] = something
fs3 = scanl (genx m n 0 0) (repeat 0)
where genx a b c d = something
Question 1: Does any of my approach the good way to solve this problem? (+ please show me an example of how to do it)
Question 2: How would you solve this kind of problem if I am in the wrong way?
This problem is similar to “Fibonacci series”, but in my opinion, there is a big difference between them.
Memoization is a common technique to solve this kind of problems.
For example, we can use it to compute Fibonacci series.
The following is a very simple illustration. It is not as good as that
zipWithsolution, but it is still a linear operation implementation.If we try to imitate the above
fibandfibs, perhaps we would write the following code.But the above
fbsis also super slow. Replacing list by array makes little difference. The reason is simple, there is no memoization when we callfbs.The answer will be more clear if we compare the type signatures of
fibsandfbs.One of them is a list of intergers, while the other is a function.
To let memoization happen, we have to implement fbs in anothing way.
e.g.
Tail recursion is anothing common approach for this kind of problems.
Last but not least, here is a mathematical solution.