blob: b37f337e8c1b4ad5cbdef77def8a0719c77caf16 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
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.
|