Solve day 9 part 2

This commit is contained in:
George Thomas 2025-12-09 13:37:39 +00:00
parent 0e2a3c81ac
commit 2862457529
3 changed files with 66 additions and 2 deletions

View File

@ -23,6 +23,7 @@ module Pre (
module Data.Text, module Data.Text,
module Data.Text.Encoding, module Data.Text.Encoding,
module Data.Traversable, module Data.Traversable,
module Data.Tuple.Extra,
module Data.Void, module Data.Void,
module Data.Word, module Data.Word,
module Linear, module Linear,
@ -38,6 +39,8 @@ module Pre (
digitsToInt, digitsToInt,
listIndex, listIndex,
allUnorderedPairs, allUnorderedPairs,
adjacentPairs,
sortPair,
) )
where where
@ -76,6 +79,7 @@ import Data.Text (Text)
import Data.Text.Encoding (encodeUtf8) import Data.Text.Encoding (encodeUtf8)
import Data.Text.Lazy qualified as TL import Data.Text.Lazy qualified as TL
import Data.Traversable import Data.Traversable
import Data.Tuple.Extra ((&&&))
import Data.Void import Data.Void
import Data.Word import Data.Word
import Linear (V2 (..)) import Linear (V2 (..))
@ -110,3 +114,11 @@ listIndex n =
allUnorderedPairs :: Bool -> [a] -> [(a, a)] allUnorderedPairs :: Bool -> [a] -> [(a, a)]
allUnorderedPairs diagonals = concat . join (zipWith (flip $ map . (,)) . (bool tail toList diagonals) . tails) allUnorderedPairs diagonals = concat . join (zipWith (flip $ map . (,)) . (bool tail toList diagonals) . tails)
adjacentPairs :: [b] -> [(b, b)]
adjacentPairs = \case
[] -> []
x : xs -> zip (x : xs) xs
sortPair :: (Ord a) => (a, a) -> (a, a)
sortPair (a, b) = if a <= b then (a, b) else (b, a)

View File

@ -8,14 +8,65 @@ puzzle :: Puzzle
puzzle = puzzle =
Puzzle Puzzle
{ number = 9 { number = 9
, parser = const $ (V2 @Int <$> decimal <* single ',' <*> decimal) `sepEndBy1` newline , parser = const $ (V2 <$> decimal <* single ',' <*> decimal) `sepEndBy1` newline
, parts = , parts =
[ TL.show [ TL.show
. maximum . maximum
. fmap ((\(V2 x y) -> x * y) . (+ 1) . fmap abs . uncurry (-)) . fmap (squareSize . uncurry Square)
. fromMaybe (error "input too small") . fromMaybe (error "input too small")
. nonEmpty . nonEmpty
. allUnorderedPairs False . allUnorderedPairs False
, \points ->
let path =
fromMaybe (error "malformed line")
. traverse mkLine
$ (last points', head points') :| adjacentPairs points
where
points' = fromMaybe (error "empty input") $ nonEmpty points
in TL.show
. snd
. fromMaybe (error "no solutions")
. find (not . flip any path . lineIntersectsSquare . fst)
. sortOn (Down . snd)
. fmap ((id &&& squareSize) . uncurry Square)
$ allUnorderedPairs False points
] ]
, extraTests = mempty , extraTests = mempty
} }
data Square = Square
{ corner1 :: V2 Int
, corner2 :: V2 Int
}
deriving (Show)
squareSize :: Square -> Int
squareSize Square{corner1, corner2} = (\(V2 x y) -> x * y) . (+ 1) . fmap abs $ corner1 - corner2
data Line
= LineHorizontal {y :: Int, x1 :: Int, x2 :: Int}
| LineVertical {x :: Int, y1 :: Int, y2 :: Int}
deriving (Show)
mkLine :: (V2 Int, V2 Int) -> Maybe Line
mkLine (V2 x1 y1, V2 x2 y2)
| y1 == y2 = Just $ LineHorizontal{y = y1, x1, x2}
| x1 == x2 = Just $ LineVertical{x = x1, y1, y2}
| otherwise = Nothing
data Interval = Interval Int Int deriving (Show)
compareToInterval :: Int -> Interval -> Ordering
compareToInterval n (Interval l u)
| n <= l = LT
| n >= u = GT
| otherwise = EQ
squareIntervals :: Square -> V2 Interval
squareIntervals Square{corner1, corner2} = uncurry Interval . sortPair <$> liftA2 (,) corner1 corner2
lineIntersectsSquare :: Square -> Line -> Bool
lineIntersectsSquare (squareIntervals -> V2 intervalX intervalY) = \case
LineHorizontal{y, x1, x2} ->
compareToInterval y intervalY == EQ
&& compareToInterval x1 intervalX /= compareToInterval x2 intervalX
LineVertical{x, y1, y2} ->
compareToInterval x intervalX == EQ
&& compareToInterval y1 intervalY /= compareToInterval y2 intervalY

1
outputs/real/9/2 Normal file
View File

@ -0,0 +1 @@
1474699155