2013年4月17日

Haskellでcode jamに挑戦 2013予選A

2013年のcode jamに懲りずにまたまたHaskellで挑戦しました

Land of Lisp読んだばっかりだからやっぱりCommon Lispでやりたかったけど結局code jamみたいな数値計算系はHaskellの方が有利かなと思ってHaskellで挑戦しました
結局、入力のパースで散々な目にあいましたが

予選A
Xを+1、Oを-1、Tを2倍にするとして+3を上回るか-3を下回るものがあるか検索
+3を上回るか-3を下回るものが見つかったら終了
見つからなかったら「.」を検索してあったら途中、なかったら引き分けとして決着
注意点はTの2倍を最後に回すように気をつけてsmall、largeともにクリアできました

HaskellらしくX,O,Tの処理を関数の部分適応で対応したところがHaskellらしいのではないかなと思っております

しかし本題に取り組むよりも入力のパースで手間取りました
Haskellで入力をパースしてどうこうするってことをあまりやったことがないからテキストから整数に変換する方法やら入力を成形するところで大幅につまづきました
正直、途中で心が折れるところでした
import Data.List

x = (+1)
t = (*2)
o = (subtract 1)
d = (+0)

input = "xxxt....oo......"
predp 't' _ = GT
predp _ _ = LT

mapf = map f
     where f 'x' = x
    f 't' = t
    f 'o' = o
           f 'X' = x
    f 'T' = t
    f 'O' = o
    f '.' = d
    f _ = d

so = sortBy predp

r n = take 4 . drop (4 * n)
c n xs = foldr (\nn a -> (head $ drop (4 * nn + n) xs) : a) [] [0..3]
lurb xs = foldr f [] [0..3]
     where f 0 a = (head xs) : a
    f 1 a = (head $ drop 5 xs) : a
    f 2 a = (head $ drop 10 xs) : a
    f 3 a = (head $ drop 15 xs) : a
rulb xs = foldr f [] [0..3]
     where f 0 a = (head $ drop 3 xs) : a
    f 1 a = (head $ drop 6 xs) : a
    f 2 a = (head $ drop 9 xs) : a
    f 3 a = (head $ drop 12 xs) : a
app = foldl (\n x -> x n) 0

inputs = map (app . mapf . so) $ (map (\n -> r n input) [0..3]) ++ (map (\n -> c n input) [0..3]) ++ [(lurb input)] ++ [(rulb input)]
inlist i = map (app . mapf .so ) $ (map (\n -> r n i) [0..3]) ++ (map (\n -> c n i) [0..3]) ++ [(lurb i)] ++ [(rulb i)]

rInt s = read s :: Int

res [] s n
  | any (=='.') s = "Case #" ++ show n ++ ": Game has not completed"
  | otherwise = "Case #" ++ show n ++ ": Draw"
res (x:xs) s n
  | x > 3 = "Case #" ++ show n ++ ": X won"
  | x < -3 = "Case #" ++ show n ++ ": O won"
  | otherwise = res xs s n

main = do cs <- getContents
   putStr $ unlines $ map (\(s, m) -> res (inlist s) s (m + 1)) $ map (\n -> (foldl (++) "" $ take 4 $ drop ((n * 5) + 1) $ lines cs, n)) [0..((rInt $ head $ lines cs) - 1)]