dynamic programming - Counting change in Haskell -
i came across following solution dp problem of counting change:
count' :: int -> [int] -> int count' cents coins = aux coins !! cents aux = foldr addcoin (1:repeat 0) addcoin c oldlist = newlist newlist = (take c oldlist) ++ zipwith (+) newlist (drop c oldlist)
it ran faster naive top-down recursive solution, , i'm still trying understand it.
i given list of coins, aux
computes every solution positive integers. solution amount index list @ position.
i'm less clear on addcoin
, though. somehow uses value of each coin draw elements list of coins? i'm struggling find intuitive meaning it.
the fold in aux
ties brain in knots. why 1:repeat 0
initial value? represent?
it's direct translation of imperative dp algorithm problem, looks (in python):
def count(cents, coins): solutions = [1] + [0]*cents # [1, 0, 0, 0, ... 0] coin in coins: in range(coin, cents + 1): solutions[i] += solutions[i - coin] return solutions[cents]
in particular, addcoin coin solutions
corresponds to
for in range(coin, cents + 1): solutions[i] += solutions[i - coin]
except addcoin
returns modified list instead of mutating old one. haskell version, result should have unchanged section @ beginning until coin
-th element, , after must implement solutions[i] += solutions[i - coin]
.
we realize unchanged part take c oldlist
, modified part zipwith (+) newlist (drop c oldlist)
. in modified part add i
-th elements of old list , i - coin
-th elements of resulting list. shifting of indices implicit in drop
, take
operations.
a simpler, classic example kind of shifting , recursive definition fibonacci numbers:
fibs = 0 : 1 : zipwith (+) fibs (tail fibs)
we write imperatively as
def fibs(limit): res = [0, 1] + [0]*(limit - 2) in range(2, limit): res[i] = res[i - 2] + res[i - 1] return res
turning coin change, foldr addcoin (1:repeat 0)
corresponds initialization of solutions
, loop on coins, change initial list infinite instead of finite (because laziness lets that).
Comments
Post a Comment