-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday14.hs
More file actions
50 lines (40 loc) · 1.57 KB
/
Copy pathday14.hs
File metadata and controls
50 lines (40 loc) · 1.57 KB
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
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE OverloadedRecordDot #-}
module Main where
import Data.Char (isDigit)
import Data.Bifunctor (bimap)
import Data.Maybe (mapMaybe)
import Data.Map qualified as M
data Robot = Robot {p :: (Int, Int), v :: (Int, Int)} deriving (Show, Eq, Ord)
data Tiles = Tiles {w :: Int, h :: Int} deriving (Show)
main = interact (unlines . sequence [uncurry part1] . parse)
part1 :: Tiles -> [Robot] -> String
part1 tiles = ("Part 1: " ++) . show . product . M.map length . quadrants tiles . map (move tiles 100)
quadrants :: Tiles -> [Robot] -> M.Map Int [Robot]
quadrants (Tiles {..}) = M.fromListWith (++) . mapMaybe quadrant
where
quadrant r = do
x <- divide w (fst r.p)
y <- divide h (snd r.p)
return (2 * y + x, [r])
divide :: Int -> Int -> Maybe Int
divide size v
| v == mid = Nothing
| otherwise = return (v `div` (mid + 1))
where
mid = size `div` 2
move :: Tiles -> Int -> Robot -> Robot
move (Tiles {..}) t r = r { p = (dx, dy) }
where
teleport upperBound v = v `mod` upperBound
dx = teleport w (fst r.p + t * fst r.v)
dy = teleport h (snd r.p + t * snd r.v)
parse :: String -> (Tiles, [Robot])
parse = mkTiles . map mkRobot . lines
where
vec = bimap (read . drop 2) (read . tail) . span (/= ',')
mkRobot input = let (p : v : _) = words input in
Robot (vec p) (vec v)
mkTiles robots
| any ((> 11) . fst . p) robots = (Tiles { w = 101, h = 103 }, robots)
| otherwise = (Tiles { w = 7, h = 11 }, robots)