2022-12-09 08:02:19 +01:00
import Linear.V2
import Data.List
2022-12-10 05:58:58 +01:00
import Data.List.Split
2022-12-09 08:02:19 +01:00
import Control.Lens
type Rope = ( V2 Int , V2 Int )
main :: IO ()
main = do
2022-12-10 05:58:58 +01:00
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
2022-12-09 08:02:19 +01:00
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
2022-12-10 05:58:58 +01:00
| abs a == abs b = if abs a == 2 then x ` div ` 2 else 0
2022-12-09 08:02:19 +01:00
| abs a + abs b == 1 = 0
2022-12-10 05:58:58 +01:00
| 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