46 lines
1.1 KiB
Haskell
46 lines
1.1 KiB
Haskell
import Data.List
|
|
import Linear.V2
|
|
|
|
type Rope = (V2 Int, V2 Int)
|
|
|
|
main :: IO ()
|
|
main = do
|
|
input <- concatMap (parse . words) . lines <$> readFile "input"
|
|
print $ length $ nub $ day9 1 input
|
|
print $ length $ nub $ day9 9 input
|
|
|
|
day9 :: Int -> [V2 Int] -> [V2 Int]
|
|
day9 n input
|
|
| n > 1 = day9 (pred n) (zipWith (-) (tail field) field)
|
|
| otherwise = field
|
|
where
|
|
field =
|
|
concatMap nub $
|
|
group $ reverse $ snd $ moveAll ((V2 0 0, V2 0 0), []) input
|
|
|
|
parse :: [String] -> [V2 Int]
|
|
parse [dir, len]
|
|
| dir == "R" = f $ V2 1 0
|
|
| dir == "L" = f $ V2 (-1) 0
|
|
| dir == "U" = f $ V2 0 1
|
|
| dir == "D" = f $ V2 0 (-1)
|
|
where
|
|
f = replicate (read len)
|
|
|
|
moveAll :: (Rope, [V2 Int]) -> [V2 Int] -> (Rope, [V2 Int])
|
|
moveAll r (x:xs) = moveAll (move r x) xs
|
|
moveAll ((head, tail), xs) _ = ((head, tail), tail : xs)
|
|
|
|
move :: (Rope, [V2 Int]) -> V2 Int -> (Rope, [V2 Int])
|
|
move ((head, tail), ps) m = ((head + m, newTail), tail : ps)
|
|
where
|
|
newTail = tailMove (head + m - tail) + tail
|
|
|
|
tailMove :: V2 Int -> V2 Int
|
|
tailMove (V2 a b) = V2 (f a) (f b)
|
|
where
|
|
f x
|
|
| abs x == 2 = signum x
|
|
| abs a + abs b <= 2 = 0
|
|
| otherwise = x
|