-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathday08.hs
More file actions
47 lines (36 loc) · 1.32 KB
/
Copy pathday08.hs
File metadata and controls
47 lines (36 loc) · 1.32 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
#!/usr/bin/env runghc
module Main where
import Control.Monad (msum)
import Data.List (find, sortOn)
import Data.Maybe (fromMaybe)
import Data.Set qualified as S
type Point = (Int, Int, Int)
main = interact (unlines . sequence [part1, part2] . parse)
part1 :: [Point] -> String
part1 = ("Part 1: " ++) . show . score . go
where
go xs = scanCircuits xs !! if length xs > 100 then 1000 else 10
score = product . take 3 . sortOn negate . map S.size
part2 :: [Point] -> String
part2 = ("Part 2: " ++) . show . fromMaybe 0 . msum . go
where
go xs = zipWith match (closest xs) (drop 1 $ scanCircuits xs)
match ((x, _, _), (x', _, _)) state = case state of
[_] -> Just (x * x')
_ -> Nothing
scanCircuits xs = scanl (flip joinCircuits) (circuits xs) (closest xs)
joinCircuits :: (Point, Point) -> [S.Set Point] -> [S.Set Point]
joinCircuits (q, p) = join (S.fromList [q, p])
where
join acc [] = [acc]
join acc (cir : xs)
| null (acc `S.intersection` cir) = cir : join acc xs
| otherwise = join (acc <> cir) xs
circuits = map S.singleton
closest = sortOn distSq . pairs
where
distSq ((x, y, z), (x', y', z')) = (x' - x) ^ 2 + (y' - y) ^ 2 + (z' - z) ^ 2
pairs [] = []
pairs (x : xs) = [(x, y) | y <- xs] ++ pairs xs
parse :: String -> [Point]
parse = map (read . (\x -> "(" ++ x ++ ")")) . lines