lifegame
『プログラミング Haskell』を半分程度読み終えたのにコードを一行も書いたことが無いというのは流石にまずいだろうと思ってライフゲームを実装してみた.というかこのライフゲーム自体もプログラムとして書いた経験が無いという事が判明したのですが,大体の場合よく知らない言語で初めて書くプログラムは一度書いたことのあるアルゴリズムだと思うので,なんか得したなーという気分になった.
あとこのプログラム書いてて思ったのが,GHC の吐くエラーメッセージ分かりにくいという事.まあたぶん慣れの問題だと思うけどどうなんだろう….
data Flag = Live | Dead type OrderedBoard = [Flag] gen :: Int -> [(Int, Int)] -> OrderedBoard gen sidelen pos = map (\(n, _) -> bool_to_flag (elem (n `div` sidelen, n `rem` sidelen) pos)) (zip [0,1..(sidelen^2-1)] (replicate (sidelen^2) Dead)) bool_to_flag :: Bool -> Flag bool_to_flag True = Live bool_to_flag False = Dead encode :: OrderedBoard -> [Int] encode board = map encode_1 board encode_1 :: Flag -> Int encode_1 Live = 1 encode_1 Dead = 0 next_state :: OrderedBoard -> OrderedBoard next_state board = map (live_or_dead board) (zip [0,1..length board] board) live_or_dead :: OrderedBoard -> (Int, Flag) -> Flag live_or_dead board (i, flag) = judge flag (foldl count_live_cell 0 (map (\n -> board !! n) (neighbors (fromEnum (sqrt (fromIntegral (length board)))) i))) judge :: Flag -> Int -> Flag judge _ 3 = Live judge Live 2 = Live judge _ _ = Dead count_live_cell :: Int -> Flag -> Int count_live_cell n Live = n + 1 count_live_cell n Dead = n neighbors :: Int -> Int -> [Int] neighbors sidelen n = filter (\index -> index >= 0 && index < sidelen^2 && index /= n) (neighbors_1 sidelen n) neighbors_1 :: Int -> Int -> [Int] neighbors_1 sidelen n | n < 0 = [] | n > sidelen^2 = [] | n `rem` sidelen == 0 = [n - sidelen, n - sidelen + 1, n, n + 1, n + sidelen, n + sidelen + 1] | n `rem` sidelen == sidelen - 1 = [n - sidelen - 1, n - sidelen, n - 1, n, n + sidelen - 1, n + sidelen] | otherwise = [n - sidelen - 1, n - sidelen, n - sidelen + 1, n - 1, n, n + 1, n + sidelen - 1, n + sidelen, n + sidelen + 1]