-
Notifications
You must be signed in to change notification settings - Fork 0
/
Day12.hs
70 lines (55 loc) · 1.82 KB
/
Day12.hs
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
module Day12
( part1
, part2
) where
import Control.Lens.Getter ((^.))
import Data.Sequence (fromList)
import Helpers.Parsers (integers)
import Helpers.Search (findPattern)
import Linear.V2 (V2 (..))
import Linear.V3 (V3 (..), _x, _y, _z)
import Linear.Vector (Additive)
data Moon =
Moon Pos Vel
type Pos = V3 Int
type Vel = V3 Int
checkPatterns :: [[Moon]] -> Int
checkPatterns moonRounds = foldr1 lcm patterns
where
patterns =
concatMap
(\x ->
map
(\v ->
findPattern 0 1000 (==) . fromList . map (x . (!! v)) $
moonRounds)
[0 .. 3])
[projectX, projectY, projectZ]
projectX :: Moon -> V2 Int
projectX (Moon p v) = V2 (p ^. _x) (v ^. _x)
projectY :: Moon -> V2 Int
projectY (Moon p v) = V2 (p ^. _y) (v ^. _y)
projectZ :: Moon -> V2 Int
projectZ (Moon p v) = V2 (p ^. _z) (v ^. _z)
doRound :: [Moon] -> [Moon]
doRound moons = map (\x -> velocity . foldr gravity x $ moons) moons
velocity :: Moon -> Moon
velocity (Moon p v) = Moon (p + v) v
gravity :: Moon -> Moon -> Moon
gravity (Moon (V3 a b c) _) (Moon (V3 x y z) vel) =
Moon (V3 x y z) (vel + V3 (signum (a - x)) (signum (b - y)) (signum (c - z)))
totalEnergy :: Moon -> Int
totalEnergy (Moon (V3 x y z) (V3 dx dy dz)) =
(abs x + abs y + abs z) * (abs dx + abs dy + abs dz)
makeMoons :: String -> [Moon]
makeMoons = map (\[x, y, z] -> Moon (V3 x y z) (V3 0 0 0)) . integers
part1 :: Bool -> String -> String
part1 test =
show .
sum . map totalEnergy . last . take (n + 1) . iterate doRound . makeMoons
where
n
| test = 10
| otherwise = 1000
part2 :: Bool -> String -> String
part2 _ = show . checkPatterns . take 500001 . iterate doRound . makeMoons