Solve day 9 part 2
This commit is contained in:
parent
0e2a3c81ac
commit
2862457529
@ -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)
|
||||||
|
|||||||
@ -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
1
outputs/real/9/2
Normal file
@ -0,0 +1 @@
|
|||||||
|
1474699155
|
||||||
Loading…
x
Reference in New Issue
Block a user