wvogel日記

自分用の技術備忘録が多めです.

状態処理

PC甲子園、2010年本戦の問題第3問で、セグメント数字表示機への指示の遷移を出力せよ、みたいな問題がありました。
詳しくは公式HPのPDF参照。


これは、Stateモナド使って解けるなーと思い。
モナドやろうやろうと思いつつ、なかなか題材がなかったので、これを機にやってみた

import Control.Monad
import Control.Monad.State

type SegState = ([Int],[[Int]])
type SegCommand = [[Int]]

seg = [[1,1,1,1,1,1,0],--0
       [0,1,1,0,0,0,0],--1
       [1,1,0,1,1,0,1],--2
       [1,1,1,1,0,0,1],--3
       [0,1,1,0,0,1,1],--4
       [1,0,1,1,0,1,1],--5
       [1,0,1,1,1,1,1],--6
       [1,1,1,0,0,1,0],--7
       [1,1,1,1,1,1,1],--8
       [1,1,1,1,0,1,1]]--9

start = ([0,0,0,0,0,0,0],[])
--(切り替えた後のセグメントの状態,切り替えるための指示)

order :: [Int]->[Int]->[Int]
order [] [] = []
order (a:as) (b:bs) = case a == b of
                       True  -> 0:order as bs
                       False -> 1:order as bs

deal_input :: [Int] -> State SegState SegCommand
deal_input [] = do (_,command) <- get
                   return command
deal_input (x:xs) = do (now,command) <- get
                       put (seg!!x,command++[order now (seg!!x)])
                       deal_input xs

main = do n <- getLine
          cs <- getContents
          forM_ (evalState
             (deal_input.map read.take (read n) $ lines cs) start)
              print

実際の問題とは、出力される数字の順番は逆になっています。
私が問題をちゃんと読んでなかったから笑
本来は、-1を入力するまで処理し続けるようにしないといけないんですが、
それは、昔type the numbersをHaskellで作ったときに実現しているのであれと同様。
自分でやる分には、応用より実際が大事と思っているので。