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
