Life Goes On

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

unfoldr ← iterate

勉強会で unfoldr を教わったので、unfoldr 厨になってみる。
どこに使えるかなと考えてみて、種からリストを生成してるんだから iterate と同じじゃん!と思って、26問目を書き換えてみました。
もともとのコード。「ウサギとカメ」です。

cyclePart :: [Int] -> [Int]
cyclePart xs
  | (t' == 0) = []
  | otherwise = t' : (takeWhile (/= t') $ map fst ys)
  where
    ((t', r') : ys) = dropWhile (\ (t, r) -> t /= r) $
      zip xs $ map head $ iterate (drop 2) $ tail xs

rems :: Int -> [Int]
rems n = iterate next 1
  where next rem = mod (rem * 10) n

で、iterate を使ってる2ヶ所を unfoldr にしてみたコード。有限のリストは有限のリストとして扱っているので、こっちの方が厳密ですね。
case と if のどちらを使うかとか、しょうもないことで悩んでしまった。

cyclePart :: [Int] -> [Int]
cyclePart xs =
  case map fst $ dropWhile (\ (t, r) -> t /= r) $ zip xs $ unfoldr phi xs of
    [] -> []
    (y:ys) -> y : takeWhile (/= y) ys
  where phi ys = case drop 1 ys of
                   [] -> Nothing
                   (z:zs) -> Just (z, zs)

rems :: Int -> [Int]
rems n = unfoldr phi 1
  where phi r = let m = mod (r * 10) n
                in if m == 0 then Nothing else Just (m, m)