2025-12-08 13:40:55 +00:00
|
|
|
module Puzzles.Day8 (puzzle) where
|
|
|
|
|
|
|
|
|
|
import Pre
|
|
|
|
|
|
2025-12-08 22:48:29 +00:00
|
|
|
import Control.Lens
|
2025-12-08 21:58:47 +00:00
|
|
|
import Data.DisjointSet qualified as DS
|
|
|
|
|
import Data.Text.Lazy qualified as TL
|
|
|
|
|
import Linear.Metric
|
|
|
|
|
import Linear.V3
|
|
|
|
|
|
2025-12-08 13:40:55 +00:00
|
|
|
puzzle :: Puzzle
|
|
|
|
|
puzzle =
|
|
|
|
|
Puzzle
|
|
|
|
|
{ number = 8
|
2025-12-08 22:43:17 +00:00
|
|
|
, parser = \isRealData ->
|
|
|
|
|
(if isRealData then 1000 else 10,)
|
|
|
|
|
<$> (V3 <$> decimal <* single ',' <*> decimal <* single ',' <*> decimal) `sepEndBy` newline
|
2025-12-08 13:40:55 +00:00
|
|
|
, parts =
|
2025-12-08 22:42:57 +00:00
|
|
|
[ uncurry \n ->
|
|
|
|
|
TL.show
|
|
|
|
|
. product
|
|
|
|
|
. take 3
|
|
|
|
|
. sortOn Down
|
|
|
|
|
. map length
|
|
|
|
|
. DS.toLists
|
2025-12-09 00:02:54 +00:00
|
|
|
. maybe (error "not enough boxes") snd
|
|
|
|
|
. listIndex n
|
2025-12-08 22:42:57 +00:00
|
|
|
. connectBoxes
|
|
|
|
|
, uncurry . const $
|
|
|
|
|
TL.show
|
2025-12-08 22:48:29 +00:00
|
|
|
. uncurry ((*) `on` view _x)
|
|
|
|
|
. maybe (error "sets never unified") fst
|
2025-12-08 22:42:57 +00:00
|
|
|
. lastMay
|
|
|
|
|
. takeWhile ((> 1) . DS.sets . snd)
|
|
|
|
|
. connectBoxes
|
2025-12-08 13:40:55 +00:00
|
|
|
]
|
|
|
|
|
, extraTests = mempty
|
|
|
|
|
}
|
2025-12-08 21:58:47 +00:00
|
|
|
|
|
|
|
|
connectBoxes :: [V3 Int] -> [((V3 Int, V3 Int), DS.DisjointSet (V3 Int))]
|
|
|
|
|
connectBoxes boxes = zip allPairs $ scanl (flip $ uncurry DS.union) (foldMap DS.singleton boxes) allPairs
|
|
|
|
|
where
|
2025-12-09 00:26:22 +00:00
|
|
|
allPairs = sortOn (quadrance . uncurry (-)) $ allUnorderedPairs boxes
|
2025-12-08 21:58:47 +00:00
|
|
|
|
|
|
|
|
allUnorderedPairs :: [a] -> [(a, a)]
|
2025-12-09 00:26:22 +00:00
|
|
|
allUnorderedPairs = concat . join (zipWith (flip $ map . (,)) . tail . tails)
|