--- Writeup at https://work.njae.me.uk/2022/12/04/advent-of-code-2022-day-4/
+-- Writeup at https://work.njae.me.uk/2022/12/10/advent-of-code-2022-day-9/
import AoC
import Data.Text (Text)
type Path = [Position]
data Rope = Rope
- { _headR :: Position
- , _tailR :: Position
+ { _headK :: Position
+ , _knots :: [Position]
, _trace :: Trace
} deriving (Show, Eq)
makeLenses ''Rope
let path = successfulParse text
let steps = expandPath path
print $ part1 steps
+ print $ part2 steps
part1 :: Path -> Int
part1 steps = S.size $ rope' ^. trace
- where rope' = ropeSteps newRope steps
+ where rope' = ropeSteps (newRope 1) steps
+
+part2 steps = S.size $ rope' ^. trace
+ where rope' = ropeSteps (newRope 9) steps
+
expandPath :: [Direction] -> Path
expandPath = concatMap expandStep
towards :: Position -> Position -> Position
towards p1 p2 = signum $ p2 ^-^ p1
-newRope :: Rope
-newRope = Rope { _headR = V2 0 0, _tailR = V2 0 0, _trace = S.singleton (V2 0 0) }
+newRope :: Int -> Rope
+newRope n = Rope { _headK = V2 0 0, _knots = replicate n (V2 0 0), _trace = S.singleton (V2 0 0) }
ropeSteps :: Rope -> Path -> Rope
ropeSteps rope steps = foldl' ropeStep rope steps
ropeStep :: Rope -> Position -> Rope
-ropeStep rope step = rope & headR .~ hr
- & tailR .~ tailR'
- & trace %~ S.insert tailR'
- where hr = (rope ^. headR) ^+^ step
- tr = rope ^. tailR
- tailR' = if tr `touching` hr
- then rope ^. tailR
- else tr ^+^ (tr `towards` hr)
+ropeStep rope step = rope & headK .~ h
+ & knots .~ (reverse kts')
+ & trace %~ S.insert (head kts')
+ where h = (rope ^. headK) ^+^ step
+ kts = rope ^. knots
+ (_, kts') = foldl' knotStep (h, []) kts
+
+
+-- foldl' (f) (hr, []) knots
+
+knotStep (h, ks) kt = (kt', (kt':ks))
+ where kt' = if kt `touching` h
+ then kt
+ else kt ^+^ (kt `towards` h)
+
-- Parse the input file