{-# Language QuasiQuotes, TemplateHaskell, ImportQualifiedPost #-}
module Main (main) where
import Advent (format, stageTH)
import Advent.Coord
import Control.Applicative (liftA2)
import Data.Foldable (asum)
import Data.List (foldl1')
import Data.Map (Map)
import Data.Map qualified as Map
data D = DU | DD | DL | DR
deriving Int -> D -> ShowS
[D] -> ShowS
D -> String
(Int -> D -> ShowS) -> (D -> String) -> ([D] -> ShowS) -> Show D
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> D -> ShowS
showsPrec :: Int -> D -> ShowS
$cshow :: D -> String
show :: D -> String
$cshowList :: [D] -> ShowS
showList :: [D] -> ShowS
Show
stageTH
toUnitVector :: D -> Coord
toUnitVector :: D -> Coord
toUnitVector D
DU = Coord
north
toUnitVector D
DD = Coord
south
toUnitVector D
DL = Coord
west
toUnitVector D
DR = Coord
east
main :: IO ()
IO ()
main =
do (Int
p1,Int
p2) <- [[(D, Int)]] -> (Int, Int)
answers ([[(D, Int)]] -> (Int, Int)) -> IO [[(D, Int)]] -> IO (Int, Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [format|2019 3 ((@D%u)&,%n)*|]
Int -> IO ()
forall a. Show a => a -> IO ()
print Int
p1
Int -> IO ()
forall a. Show a => a -> IO ()
print Int
p2
answers :: [[(D, Int)]] -> (Int, Int)
answers :: [[(D, Int)]] -> (Int, Int)
answers [[(D, Int)]]
xs = (Map Coord Int -> Int
forall a. Map Coord a -> Int
nearestDistanceToOrigin Map Coord Int
intersections, Map Coord Int -> Int
forall a. Ord a => Map Coord a -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum Map Coord Int
intersections)
where
intersections :: Map Coord Int
intersections = [[(D, Int)]] -> Map Coord Int
pathIntersections [[(D, Int)]]
xs
nearestDistanceToOrigin :: Map Coord a -> Int
nearestDistanceToOrigin :: forall a. Map Coord a -> Int
nearestDistanceToOrigin = [Int] -> Int
forall a. Ord a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
minimum ([Int] -> Int) -> (Map Coord a -> [Int]) -> Map Coord a -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Coord -> Int) -> [Coord] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map (Coord -> Coord -> Int
manhattan Coord
origin) ([Coord] -> [Int])
-> (Map Coord a -> [Coord]) -> Map Coord a -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map Coord a -> [Coord]
forall k a. Map k a -> [k]
Map.keys
pathIntersections :: [[(D,Int)]] -> Map Coord Int
pathIntersections :: [[(D, Int)]] -> Map Coord Int
pathIntersections = (Map Coord Int -> Map Coord Int -> Map Coord Int)
-> [Map Coord Int] -> Map Coord Int
forall a. HasCallStack => (a -> a -> a) -> [a] -> a
foldl1' ((Int -> Int -> Int)
-> Map Coord Int -> Map Coord Int -> Map Coord Int
forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWith Int -> Int -> Int
forall a. Num a => a -> a -> a
(+)) ([Map Coord Int] -> Map Coord Int)
-> ([[(D, Int)]] -> [Map Coord Int])
-> [[(D, Int)]]
-> Map Coord Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([(D, Int)] -> Map Coord Int) -> [[(D, Int)]] -> [Map Coord Int]
forall a b. (a -> b) -> [a] -> [b]
map [(D, Int)] -> Map Coord Int
distances
distances :: [(D,Int)] -> Map Coord Int
distances :: [(D, Int)] -> Map Coord Int
distances [(D, Int)]
steps = (Int -> Int -> Int) -> [(Coord, Int)] -> Map Coord Int
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith Int -> Int -> Int
forall a. Ord a => a -> a -> a
min ([Coord] -> [Int] -> [(Coord, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip ([(D, Int)] -> [Coord]
generatePath [(D, Int)]
steps) [Int
1..])
generatePath :: [(D,Int)] -> [Coord]
generatePath :: [(D, Int)] -> [Coord]
generatePath
= (Coord -> Coord -> Coord) -> [Coord] -> [Coord]
forall a. (a -> a -> a) -> [a] -> [a]
scanl1 Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
(+)
([Coord] -> [Coord])
-> ([(D, Int)] -> [Coord]) -> [(D, Int)] -> [Coord]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((D, Int) -> [Coord]) -> [(D, Int)] -> [Coord]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(D
d,Int
n) -> Int -> Coord -> [Coord]
forall a. Int -> a -> [a]
replicate Int
n (D -> Coord
toUnitVector D
d))