import Data.List (sortBy,minimumBy) import Data.Maybe (fromMaybe) import Text.Parsec data Vec = Vec { x :: Int, y :: Int } deriving (Eq,Show) data Robot = Robot { pos :: Vec, vel :: Vec } deriving Show data Conf = Conf { width :: Int, height :: Int} doParse :: String -> [Robot] doParse s = case parse inputp "" s of Left e -> error $ show e Right xs -> xs inputp :: Parsec String () [Robot] inputp = sepBy robotp newline robotp :: Parsec String () Robot robotp = Robot <$> posp <* char ' ' <*> velp posp :: Parsec String () Vec posp = Vec <$ string "p=" <*> number <* char ',' <*> number velp :: Parsec String () Vec velp = Vec <$ string "v=" <*> number <* char ',' <*> number number :: Parsec String () Int number = ((read .) . (:)) . fromMaybe '0' <$> optionMaybe (char '-') <*> many1 digit update :: Conf -> Robot -> Robot update c (Robot (Vec x y) v@(Vec vx vy)) = wrap c $ Robot (Vec (x+vx) (y+vy)) v wrap :: Conf -> Robot -> Robot wrap c = wrapH c . wrapV c wrapH :: Conf -> Robot -> Robot wrapH c r | tooLeft c r = wrapRight c r | tooRight c r = wrapLeft c r | otherwise = r where tooLeft _ (Robot (Vec x _) _) = x < 0 tooRight (Conf w _) (Robot (Vec x _) _) = x >= w wrapRight (Conf w _) r@(Robot (Vec x y) _) = r { pos = Vec (x+w) y } wrapLeft (Conf w _) r@(Robot (Vec x y) _) = r { pos = Vec (x-w) y } wrapV :: Conf -> Robot -> Robot wrapV c r | tooHigh c r = wrapDown c r | tooLow c r = wrapUp c r | otherwise = r where tooHigh _ (Robot (Vec _ y) _) = y < 0 tooLow (Conf _ h) (Robot (Vec _ y) _) = y >= h wrapDown (Conf _ h) r@(Robot (Vec x y) _) = r { pos = Vec x (y+h) } wrapUp (Conf _ h) r@(Robot (Vec x y) _) = r { pos = Vec x (y-h) } render :: Conf -> [Robot] -> String render (Conf w h) rs = unlines [ [ f $ Vec x y | x <- [0..w-1] ] | y <- [0..h-1] ] where f :: Vec -> Char f p | not $ any ((== p) . pos) rs = ' ' | otherwise = '#' main :: IO () main = do input <- getContents let conf = Conf 101 103 let frames = iterate (map $ update conf) . doParse $ input putStr $ unlines [ show n <> "\n" <> render conf (frames !! n) | n <- [ 103*i + 50 | i <- [0..101] ] ] -- Scroll through the output to find the tree. Note that the +50 -- is input-dependent.