{-# Language QuasiQuotes, TemplateHaskell, ImportQualifiedPost #-}
module Main where
import Data.List (transpose)
import Data.Set qualified as Set
import Advent (format, stageTH)
import Advent.Coord (Coord(..), origin, east, north, south, west, normInf)
data C
= CD
| CR
| CU
| CL
deriving Int -> C -> ShowS
[C] -> ShowS
C -> String
(Int -> C -> ShowS) -> (C -> String) -> ([C] -> ShowS) -> Show C
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> C -> ShowS
showsPrec :: Int -> C -> ShowS
$cshow :: C -> String
show :: C -> String
$cshowList :: [C] -> ShowS
showList :: [C] -> ShowS
Show
stageTH
main :: IO ()
IO ()
main =
do [(C, Int)]
input <- [format|2022 9 (@C %u%n)*|]
let knots :: [Int]
knots = [(C, Int)] -> [Int]
uniqueLocations [(C, Int)]
input
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int]
knots [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
1)
Int -> IO ()
forall a. Show a => a -> IO ()
print ([Int]
knots [Int] -> Int -> Int
forall a. HasCallStack => [a] -> Int -> a
!! Int
9)
uniqueLocations :: [(C,Int)] -> [Int]
uniqueLocations :: [(C, Int)] -> [Int]
uniqueLocations
= ([Coord] -> Int) -> [[Coord]] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map [Coord] -> Int
forall a. Ord a => [a] -> Int
countUnique
([[Coord]] -> [Int])
-> ([(C, Int)] -> [[Coord]]) -> [(C, Int)] -> [Int]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[Coord]] -> [[Coord]]
forall a. [[a]] -> [[a]]
transpose
([[Coord]] -> [[Coord]])
-> ([(C, Int)] -> [[Coord]]) -> [(C, Int)] -> [[Coord]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Coord] -> C -> [Coord]) -> [Coord] -> [C] -> [[Coord]]
forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl [Coord] -> C -> [Coord]
stepRope (Coord -> [Coord]
forall a. a -> [a]
repeat Coord
origin)
([C] -> [[Coord]])
-> ([(C, Int)] -> [C]) -> [(C, Int)] -> [[Coord]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((C, Int) -> [C]) -> [(C, Int)] -> [C]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\(C
c,Int
n) -> Int -> C -> [C]
forall a. Int -> a -> [a]
replicate Int
n C
c)
cToVec :: C -> Coord
cToVec :: C -> Coord
cToVec C
CU = Coord
north
cToVec C
CD = Coord
south
cToVec C
CR = Coord
east
cToVec C
CL = Coord
west
stepRope ::
[Coord] ->
C ->
[Coord]
stepRope :: [Coord] -> C -> [Coord]
stepRope (Coord
x:[Coord]
xs) C
c = Coord -> [Coord] -> [Coord]
updateTails (C -> Coord
cToVec C
c Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
+ Coord
x) [Coord]
xs
stepRope [] C
_ = []
updateTails ::
Coord ->
[Coord] ->
[Coord]
updateTails :: Coord -> [Coord] -> [Coord]
updateTails Coord
h [] = [Coord
h]
updateTails Coord
h (Coord
t : [Coord]
ts)
| Coord -> Bool
isNearOrigin Coord
delta = Coord
h Coord -> [Coord] -> [Coord]
forall a. a -> [a] -> [a]
: Coord
t Coord -> [Coord] -> [Coord]
forall a. a -> [a] -> [a]
: [Coord]
ts
| Bool
otherwise = Coord
h Coord -> [Coord] -> [Coord]
forall a. a -> [a] -> [a]
: Coord -> [Coord] -> [Coord]
updateTails (Coord
t Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
+ Coord -> Coord
forall a. Num a => a -> a
signum Coord
delta) [Coord]
ts
where
delta :: Coord
delta = Coord
h Coord -> Coord -> Coord
forall a. Num a => a -> a -> a
- Coord
t
isNearOrigin :: Coord -> Bool
isNearOrigin :: Coord -> Bool
isNearOrigin Coord
c = Coord -> Int
normInf Coord
c Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2
countUnique :: Ord a => [a] -> Int
countUnique :: forall a. Ord a => [a] -> Int
countUnique = Set a -> Int
forall a. Set a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Set a -> Int) -> ([a] -> Set a) -> [a] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList