|
| 1 | +module Day14 where |
| 2 | + |
| 3 | +import Data.List |
| 4 | +import qualified Data.Set as S |
| 5 | +import Control.Monad |
| 6 | + |
| 7 | +type Pos = (Int,Int) |
| 8 | +data Robot = Robot {pos :: Pos, vel :: Pos} |
| 9 | + deriving (Show, Eq, Ord) |
| 10 | + |
| 11 | +parseRobot l = Robot (read $ "(" ++ spos ++ ")") (read $ "(" ++ svel ++ ")") |
| 12 | + where [wpos,wvel] = words l |
| 13 | + Just spos = stripPrefix "p=" wpos |
| 14 | + Just svel = stripPrefix "v=" wvel |
| 15 | + |
| 16 | +slurp = map parseRobot . lines <$> readFile "input-14" |
| 17 | + |
| 18 | +(a,b) <+> (c,d) = (a+c,b+d) |
| 19 | + |
| 20 | +wrap (w,h) (x,y) = (mod x w, mod y h) |
| 21 | + |
| 22 | +tick :: (Int,Int) -> Robot -> Robot |
| 23 | +tick (w,h) (Robot p v) = Robot (wrap (w,h) $ p <+> v) v |
| 24 | + |
| 25 | +quadrant :: (Int,Int) -> Pos -> Int |
| 26 | +quadrant (w,h) (x,y) |
| 27 | + | x < xmid && y < ymid = 1 |
| 28 | + | x < xmid && y > ymid = 2 |
| 29 | + | x > xmid && y < ymid = 3 |
| 30 | + | x > xmid && y > ymid = 4 |
| 31 | + | otherwise = 0 |
| 32 | + where xmid = div w 2 |
| 33 | + ymid = div h 2 |
| 34 | + |
| 35 | +bigLimits = (101,103) |
| 36 | + |
| 37 | +safetyScore :: (Int,Int) -> [Robot] -> Int |
| 38 | +safetyScore limits rs = product [ length [ r | r <- rs, quadrant limits (pos r) == q ] |
| 39 | + | q <- [1..4] ] |
| 40 | + |
| 41 | +part1 inp = safetyScore bigLimits $ iterate (map (tick bigLimits)) inp !! 100 |
| 42 | + |
| 43 | +heuristic1 rs = abs (left-right) |
| 44 | + where left = length $ filter ((`elem` [1,2]).quadrant bigLimits.pos) rs |
| 45 | + right = length $ filter ((`elem` [3,4]).quadrant bigLimits.pos) rs |
| 46 | + |
| 47 | +heuristic2 rs = length rs - S.size (S.fromList (map pos rs)) |
| 48 | + |
| 49 | +heuristic = heuristic2 |
| 50 | + |
| 51 | +visualize :: (Int,Int) -> [Robot] -> IO () |
| 52 | +visualize (w,h) rs = putStrLn $ unlines ls |
| 53 | + where coords = S.fromList (map pos rs) |
| 54 | + ls = [ [ if S.member (x,y) coords then '#' else '.' | x <- [0..w-1] ] | y<-[0..h-1] ] |
| 55 | + |
| 56 | +part2 inp = forM_ (take 100 minimums) $ \(i,rs) -> do |
| 57 | + putStrLn "--" |
| 58 | + visualize bigLimits rs |
| 59 | + print (heuristic rs) |
| 60 | + print i |
| 61 | + where evolution = zip [0..] $ iterate (map (tick bigLimits)) inp |
| 62 | + minimums = go (length inp) evolution |
| 63 | + go best ((i,r):rest) |
| 64 | + | heuristic r < best = (i,r):go (heuristic r) rest |
| 65 | + | otherwise = go best rest |
| 66 | + |
| 67 | +main = do |
| 68 | + --print . part1 =<< slurp |
| 69 | + part2 =<< slurp |
0 commit comments