--- /dev/null
+module one
+
+import StdEnv
+import Data.Either
+import Data.Func
+import Data.Functor
+import Data.List
+import Data.Maybe
+import Data.Tuple
+import Control.Applicative
+import Control.Monad => qualified join
+import Text
+import Text.Parsers.Simple.ParserCombinators
+
+read :: *File -> [Char]
+read f
+ # (ok, c, f) = freadc f
+ | not ok = []
+ = [c:read f]
+
+Start w
+ # (io, w) = stdio w
+ = case split ['\n\n'] $ read io of
+ [gram,ip] = case parse pGram gram of
+ Right gram
+ = (both gram ip, both
+ [(8, [[Left 42], [Left 42,Left 8]])
+ ,(11, [[Left 42, Left 31], [Left 42, Left 11, Left 31]]):gram] ip)
+where
+ both gram = length o rights o map (parse $ toParser 0 gram) o split ['\n'] o trim
+
+toParser :: Int [(Int, [[Either Int Char]])] -> Parser Char [Char]
+toParser i m = foldr (<|>) empty $ map (fmap flatten o sequence o map toP) $ fromJust $ lookup i m
+where
+ toP (Left i) = toParser i m
+ toP (Right c) = (\x->[x]) <$> pToken c
+
+pGram :: Parser Char [(Int, [[Either Int Char]])]
+pGram = pSepBy1
+ (tuple <$> pInt <* pStr [': '] <*> pSepBy1
+ (pSepBy (Left <$> pInt <|> Right <$> pChar) (pToken ' '))
+ (pStr [' | ']))
+ (pToken '\n')
+
+pInt :: Parser Char Int
+pInt = toInt o toString <$> some pDigit
+pChar :: Parser Char Char
+pChar = pToken '"' *> pAlpha <* pToken'"'
+pStr :: ([Char] -> Parser Char [Char])
+pStr = sequence o map pToken