diff options
| author | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-06 11:15:46 +0100 | 
|---|---|---|
| committer | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-06 11:15:46 +0100 | 
| commit | 11d1947a82d7b520ac76cc89b16eee4ddbafaf73 (patch) | |
| tree | 95a13cefffad048288ec9282a00829c3ad118156 | |
| parent | 04a4ecb29a92772b6e24cb12a9d3f8621415f085 (diff) | |
| download | aoc2024-11d1947a82d7b520ac76cc89b16eee4ddbafaf73.tar.gz aoc2024-11d1947a82d7b520ac76cc89b16eee4ddbafaf73.zip | |
6-1
| -rw-r--r-- | 6-1.hs | 72 | 
1 files changed, 72 insertions, 0 deletions
| @@ -0,0 +1,72 @@ +import Control.Monad (unless) +import Control.Monad.Writer +import Data.List (nub) + +type Map = [[Tile]] +data Tile = Free | Obstacle deriving (Eq) +data Coords = Coords Int Int deriving (Eq, Show) +type Vel = Coords + +width, height :: [[a]] -> Int +width = length . head +height = length + +map2 :: (a -> b) -> [[a]] -> [[b]] +map2 = map . map + +sub :: Map -> Coords -> Tile +sub m c@(Coords x y) +  | outOfBounds m c = Free +  | otherwise = m !! y !! x + +parseLines :: [[Char]] -> Map +parseLines = +  let p c = case c of +              '#' -> Obstacle +              _   -> Free +  in map2 p + +startingPosition :: [[Char]] -> Coords +startingPosition = head . coords . map2 (== '^') +  where +    coords :: [[Bool]] -> [Coords] +    coords xs = [ Coords x y | x <- [0 .. width xs  - 1] +                             , y <- [0 .. height xs - 1] +                             , xs !! y !! x +                             ] + +move :: Vel -> Coords -> Coords +move (Coords vx vy) (Coords px py) = Coords (px + vx) (py + vy) + +checkAhead :: Map -> Vel -> Coords -> Bool +checkAhead m = (((== Free) . sub m) .) . move + +turn :: Vel -> Coords -> (Coords, Vel) +turn v p = let rot (Coords x y) = Coords (-y) x +               v' = rot v +  in (move v' p, v') + +step :: Map -> Vel -> Coords -> (Coords, Vel) +step m v p = if checkAhead m v p +  then (move v p, v) +  else turn v p + +outOfBounds :: Map -> Coords -> Bool +outOfBounds m (Coords x y) = x < 0 || x >= w || y < 0 || y >= h +  where +    w = width m +    h = height m + +run :: Map -> Vel -> Coords -> Writer [Coords] () +run m v p = unless (outOfBounds m p) $ do +  tell [p] +  let (p', v') = step m v p +    in run m v' p' + +main :: IO () +main = do +  ls <- lines <$> getContents +  let m = parseLines ls +  let p = startingPosition ls +  let v = Coords 0 (-1) +  print . length . nub . execWriter $ run m v p |