第10回オフラインリアルタイムどう書くの問題をHaskellで書いた
移動場所の記録をWriterモナドで上手く書けそうな気もしますが、モナドの理解不足。。。
あとlet文、if文が多いのもイマイチか。。。
テスト処理ももっと簡潔に書きたい。
honeycomb.hs
import Control.Applicative
honeycomb = [
" T ",
" k U ",
" j H V ",
"i S I W",
" R B J ",
"h G C X",
" Q A K ",
"g F D Y",
" P E L ",
"f O M Z",
" e N a ",
" d b ",
" c "
]
honeycombW = length $ honeycomb !! 0
honeycombH = length honeycomb
directions c | c == '0' = (0,-2)
| c == '1' = (1,-1)
| c == '2' = (1,1)
| c == '3' = (0,2)
| c == '4' = (-1,1)
| c == '5' = (-1,-1)
nextPosition :: (Int, Int) -> Char -> (Int, Int)
nextPosition (x, y) d = let (dx, dy) = directions d
in (x + dx, y + dy)
validPosition :: (Int, Int) -> Bool
validPosition (x, y) = and [x >= 0, x < honeycombW, y >= 0, y < honeycombH, honeycomb !! y !! x /= ' ']
move :: ((Int, Int), String) -> Char -> ((Int, Int), String)
move ((x, y), path) d = let (x', y') = nextPosition (x, y) d
in if validPosition (x', y')
then ((x', y'), ((honeycomb !! y') !! x'):path)
else ((x, y), '!':path)
solve str = reverse $ snd $ foldl move ((3,6), "A") str
main = do
tests <- map words <$> lines <$> getContents
mapM (\t -> print $ runTest solve t) tests
where
runTest f t = f (head t) == last t
test.txt
135004 ACDABHS
1 AC
33333120 AENc!!b!M
0 AB
2 AD
3 AE
4 AF
5 AG
4532120 AFQPOEMD
051455 ABSHSj!
23334551 ADMb!cdeO
22033251 ADLKLa!ML
50511302122 AGSjkTHTU!VW
000051 ABHT!!!
1310105 ACDKJW!V
50002103140 AGSk!HU!IVIU
3112045 AEDKYXKC
02021245535 ABCIJW!JIHBS
014204 ABIBCIB
255230 ADAGAEA
443501 AFPefgQ
022321 ABCKLZ!
554452 AGRh!!Q
051024 ABSHTUH
524002 AGAFGSB
54002441132 AGQRjSRhRSGA
11010554312 ACJV!!UTkSHI
23405300554 ADMNEFOFGRi!
555353201 AGRih!gPQG
22424105 ADLMabaLD
11340202125 ACJKDCKJX!!J
4524451 AFQFPf!P
44434234050 AFPf!!e!!Pgh
00554040132 ABHk!j!i!jRG
3440403 AEOePfgf
111130 ACJW!XW
21133343125 ADKXYZ!a!Z!L
353511 AEFOPFA
22204115220 ADLZYLY!KY!X
03013541 ABABICBGB
101344 ACIVJCA
2432541 ADENbNdN
45332242015 AFQPedc!!NME
215453 ADKCAGF
45540523454 AFQh!i!RQg!!
42434302545 AFEOd!!ONOef