diff options
| author | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-06 15:53:29 +0100 | 
|---|---|---|
| committer | Laura Orvokki Kursula <lav@vampires.gay> | 2024-12-06 15:53:29 +0100 | 
| commit | dbc00d64a4a2a5feb249773a1154ec136ce831c9 (patch) | |
| tree | 0c97d2a5dc909cb1e0de1d9f2d9eadb74f4caf62 | |
| parent | 11d1947a82d7b520ac76cc89b16eee4ddbafaf73 (diff) | |
| download | aoc2024-dbc00d64a4a2a5feb249773a1154ec136ce831c9.tar.gz aoc2024-dbc00d64a4a2a5feb249773a1154ec136ce831c9.zip | |
6-2 initial version (not working)
| -rw-r--r-- | 6-2.hs | 108 | 
1 files changed, 108 insertions, 0 deletions
| @@ -0,0 +1,108 @@ +import Control.Monad.State +import Control.Parallel +import Control.Parallel.Strategies +import Data.List ((\\), intersperse, nub) + +type Map = [[Tile]] +data Tile = Free | Obstacle deriving (Eq, Show) +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 + +showMap :: Map -> String +showMap = unlines . map2 f +  where +    f :: Tile -> Char +    f Free = '.' +    f Obstacle = '#' + +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 + +-- return true if loop +run :: Map -> Vel -> Coords -> State [(Coords,Vel)] Bool +run m v p = do +  if outOfBounds m p +    then return False +    else do +    t <- get +    if (p,v) `elem` t +      then return True +      else do +      modify ((p,v):) +      let (p', v') = step m v p +        in run m v' p' + +block :: Map -> (Int, Int) -> Map +block m (x,y) = +  [ +    [ if (x',y') == (x,y) +      then Obstacle +      else sub m (Coords x' y') +    | x' <- [0 .. width m - 1] ] +  | y' <- [0 .. height m - 1] +  ] + +possibilities :: Map -> [Coords]-> [Map] +possibilities m cs = +  let coords = map (\ (Coords x y) -> (x,y)) cs +  in coords `pseq` (map (block m) coords `using` parList rseq) + +main :: IO () +main = do +  ls <- lines <$> getContents +  let m = parseLines ls +  let p = startingPosition ls +  let v = Coords 0 (-1) +  let path = map fst $ execState (run m v p) [] +  let ms = possibilities m $ nub path +  let res = ms `pseq` (map (\ n -> evalState (run n v p) []) ms `using` parList rdeepseq) +--  putStr . unlines . intersperse "--" . map (showMap . fst) . filter snd . zip ms $ res +  print . length . filter id $ res +--  print . length $ ms |