diff options
| -rw-r--r-- | 14-2.hs | 89 | 
1 files changed, 89 insertions, 0 deletions
| @@ -0,0 +1,89 @@ +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. |