This is a direct translation of the imperative DP algorithm for a problem that looks like this (in Python):
def count(cents, coins): solutions = [1] + [0]*cents
In particular, addCoin coin solutions corresponds to
for i in range(coin, cents + 1): solutions[i] += solutions[i - coin]
except that addCoin returns a modified list instead of mutating the old one. As for the Haskell version, the result should have an unchanged section at the beginning before the coin -th element, and after that we must implement solutions[i] += solutions[i - coin] .
We implement the unchanged part on take c oldlist and the modified part on zipWith (+) newlist (drop c oldlist) . In the modified part, we combine i -th elements from the old list and i - coin -th elements of the resulting list. Index movement is implicit in drop and take operations.
The simplest classic example of this kind of shift and recursive definition are Fibonacci numbers:
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
We will write it imperatively as
def fibs(limit): res = [0, 1] + [0]*(limit - 2) for i in range(2, limit): res[i] = res[i - 2] + res[i - 1] return res
Returning to changing the coin, foldr addCoin (1:repeat 0) corresponds to the initialization of solutions and the for loop on the coins, with the change that the initial list is infinite, not finite (because laziness allows us to do this).
András kovács
source share