Life Goes On

まあまあだけど楽しんでる方です

unfoldr → scanl

unfoldr の練習の続き。unfoldr で書かれているコードを、他の関数で書き換えてみる。
もとのコードはこれ。Tabulation法で両替問題を解くコードの一部です。

mkqs :: [Count] -> Coin -> [Count]
mkqs ps c = unfoldr phi (ps, [])
  where
    phi (p:ps, qs) = let q = p + prev (c-1) qs
                     in Just (q, (ps, q:qs))
    prev i xs = case genericDrop i xs of
                 []  -> 0
                 x:_ -> x

今回は種にリストが含まれているから、iterate より scanl がよさそう。
書き直したのがこれ。できあがるリストとほしいリストの型が違うから、map で変換するという操作が必要になるんだ。
なんだか unfoldr も使えそうな気がしてきた。

mkqs :: [Count] -> Coin -> [Count]
mkqs ps c = map head $ tail $ scanl phi [] ps
  where
    phi qs p = let q = p + prev (c-1) qs in q:qs
    prev i xs = case genericDrop i xs of
                 []  -> 0
                 x:_ -> x