AoC/2022/day09/day09.hs
2022-12-10 05:58:58 +01:00

54 lines
1.7 KiB
Haskell

import Linear.V2
import Data.List
import Data.List.Split
import Control.Lens
type Rope = (V2 Int,V2 Int)
main :: IO ()
main = do
input <- concat <$> map (parse . words) <$> lines <$> readFile "input" --should be 4, is 1
print $ length $ nub $ day9 1 input
print $ length $ nub $ day9 9 input
-- putStrLn $ intercalate "\n" $ print2D 10 $ sort $ nub $ day9 3 input
day9 :: Int -> [V2 Int] -> [V2 Int]
day9 n input
| n > 1 = day9 (pred n) (zipWith (-) (tail field) field)
| otherwise = field
where field = concat $ map 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 = take (read len) . repeat
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 a b) = V2 (f a) (f b)
where f x
| abs a == abs b = if abs a == 2 then x `div` 2 else 0
| abs a + abs b == 1 = 0
| otherwise = if abs x == 2 then x `div` 2 else x
p :: Int -> [Int] -> String
p n (x:xs) = if n == x then '#' : p (n+1) xs else '.' : p (n+1) (x:xs)
p _ [] = []
print2D :: Int -> [V2 Int] -> [String]
print2D n coords
| n == (pred minY) = []
| otherwise = p minX line : print2D (n-1) coords
where line = sort $ map (^._x) (filter (\(V2 _ a) -> a == n) coords)
minY = minimum $ map (^._y) coords
minX = minimum $ map (^._x) coords