import Data.Char import Control.Applicative import Control.Arrow muntil p _ x | p x = return x muntil p f x = f x >>= muntil p f back = first . (++) split (p:ps) = back [p] $ case p of ']' -> ([], ps) '[' -> uncurry back $ second split $ split ps _ -> split ps eval' [] st = return ([], st) eval' (p:ps) st = back [p] <$> case (p, st) of ('>', (xs, y:ys)) -> eval' ps (y:xs, ys) ('<', (x:xs, ys)) -> eval' ps (xs, x:ys) ('+', (xs, y:ys)) -> eval' ps (xs, (y + 1):ys) ('-', (xs, y:ys)) -> eval' ps (xs, (y - 1):ys) ('.', (xs, y:ys)) -> putChar (chr y) >> eval' ps (xs, y:ys) (',', (xs, _:ys)) -> getChar >>= \y -> eval' ps (xs, ord y:ys) (']', st) -> return (ps, st) ('[', st) -> do (ps', st') <- muntil (\(_, (_, y:_)) -> y == 0) (uncurry eval') (ps, st) let (pxs, pys) = split ps' back pxs <$> eval' pys st' eval ps = eval' ps ([], repeat 0) main = eval ">>+++++++[>++++++[>+<-]<-]+++++[>++[>>+<<-]<-]<<+++++[[>+>[-]>[-]<<[->+>+<<]>>[-<<+>>]<<>[>>.<<-]>>>.<<<<<-]]"