diff --git a/2024/haskell/app/day6/Day6.hs b/2024/haskell/app/day6/Day6.hs new file mode 100644 index 0000000..4b32386 --- /dev/null +++ b/2024/haskell/app/day6/Day6.hs @@ -0,0 +1,118 @@ +module Main (main) where + +import Control.Parallel.Strategies (parList, rdeepseq, using) +import Data.List (nub) +import Prelude hiding (Left, Right) + +-- | Part 1 +data Tile = Empty | Blockage | Guard deriving (Show, Eq) + +newtype Grid = Grid [[Tile]] deriving (Show) + +data Direction = Up | Down | Left | Right deriving (Show, Eq) + +data WalkResult = Forward (Int, Int) | BlockEncountered Direction | OutOfBounds + +tileFromString :: Char -> Tile +tileFromString '.' = Empty +tileFromString '#' = Blockage +tileFromString '^' = Guard + +guardRow :: [Char] -> [Tile] +guardRow = map tileFromString + +guardGrid :: String -> Grid +guardGrid = Grid . map guardRow . lines + +findStart :: Grid -> (Int, Int) +findStart grid = findStart' grid 0 0 + where + findStart' :: Grid -> Int -> Int -> (Int, Int) + findStart' (Grid grid') row col + | col >= length (grid' !! row) = findStart' (Grid grid') (row + 1) 0 + | (grid' !! row) !! col == Guard = (row, col) + | otherwise = findStart' (Grid grid') row (col + 1) + +move :: Direction -> (Int, Int) -> (Int, Int) +move Up (row, col) = (row - 1, col) +move Down (row, col) = (row + 1, col) +move Left (row, col) = (row, col - 1) +move Right (row, col) = (row, col + 1) + +turnRight :: Direction -> Direction +turnRight Up = Right +turnRight Right = Down +turnRight Down = Left +turnRight Left = Up + +outOfBounds :: Grid -> (Int, Int) -> Bool +outOfBounds (Grid g) (row, col) = row < 0 || row >= length g || col < 0 || col >= length (g !! row) + +stepGridWith :: Grid -> Direction -> (Int, Int) -> WalkResult +stepGridWith (Grid grid) direction pos + | outOfBounds (Grid grid) pos = OutOfBounds + | outOfBounds (Grid grid) (move direction pos) = Forward (move direction pos) + | otherwise = + let (r', c') = move direction pos + newDirection = turnRight direction + in case (grid !! r') !! c' of + Blockage -> BlockEncountered newDirection + _ -> Forward (r', c') + +walkGrid :: Grid -> Direction -> (Int, Int) -> [(Int, Int)] +walkGrid grid direction pos = + case stepGridWith grid direction pos of + OutOfBounds -> [] + Forward newPos -> pos : walkGrid grid direction newPos + BlockEncountered newDirection -> walkGrid grid newDirection pos + +part1 :: String -> IO () +part1 s = + let grid = guardGrid s + start = findStart grid + in print $ length $ nub $ walkGrid grid Up start + +-- | Part 2 +isLoop :: Direction -> (Int, Int) -> Grid -> Bool +isLoop direction pos grid = isLoop' grid direction pos [] + where + isLoop' :: Grid -> Direction -> (Int, Int) -> [((Int, Int), Direction)] -> Bool + isLoop' grid' direction' pos' visited + | (pos', direction') `elem` visited = True + | otherwise = + case stepGridWith grid' direction' pos' of + OutOfBounds -> False + Forward newPos -> isLoop' grid' direction' newPos ((pos', direction') : visited) + BlockEncountered newDirection -> isLoop' grid' newDirection pos' visited + +blockPos :: Grid -> (Int, Int) -> Grid +blockPos (Grid g) (row, col) = + let (g', gs) = splitAt row g + in Grid $ g' ++ [blockPosInCol' (g !! row) col] ++ drop 1 gs + where + blockPosInCol' :: [Tile] -> Int -> [Tile] + blockPosInCol' row' col' = + let (r, rs) = splitAt col' row' + in r ++ [Blockage] ++ drop 1 rs + +countLoopers :: Grid -> (Int, Int) -> Int +countLoopers (Grid grid) startPos = + let guardPath = nub $ walkGrid (Grid grid) Up startPos + emptyPath = filter (\(row, col) -> (grid !! row) !! col == Empty) guardPath + loops = map countLooper emptyPath `using` parList rdeepseq + in sum loops + where + countLooper :: (Int, Int) -> Int + countLooper (row, col) + | isLoop Up startPos (blockPos (Grid grid) (row, col)) = 1 + | otherwise = 0 + +part2 :: String -> IO () +part2 s = + let grid = guardGrid s + start = findStart grid + in print $ countLoopers grid start + +-- | Main +main :: IO () +main = readFile "resources/day6.txt" >>= part2 diff --git a/2024/haskell/haskell.cabal b/2024/haskell/haskell.cabal index 7d6b8a0..9ec0b8d 100644 --- a/2024/haskell/haskell.cabal +++ b/2024/haskell/haskell.cabal @@ -108,6 +108,21 @@ executable day5 , haskell default-language: Haskell2010 +executable day6 + main-is: Day6.hs + other-modules: + Paths_haskell + autogen-modules: + Paths_haskell + hs-source-dirs: + app/day6 + ghc-options: -Wall -Wcompat -Widentities -Wincomplete-record-updates -Wincomplete-uni-patterns -Wmissing-export-lists -Wmissing-home-modules -Wpartial-fields -Wredundant-constraints -threaded -rtsopts -with-rtsopts=-N + build-depends: + base >=4.7 && <5 + , haskell + , parallel + default-language: Haskell2010 + test-suite haskell-test type: exitcode-stdio-1.0 main-is: Spec.hs diff --git a/2024/haskell/package.yaml b/2024/haskell/package.yaml index f2ee127..c8bf8bd 100644 --- a/2024/haskell/package.yaml +++ b/2024/haskell/package.yaml @@ -87,6 +87,17 @@ executables: dependencies: - haskell + day6: + main: Day6.hs + source-dirs: app/day6 + ghc-options: + - -threaded + - -rtsopts + - -with-rtsopts=-N + dependencies: + - haskell + - parallel + tests: haskell-test: main: Spec.hs diff --git a/2024/haskell/resources/day6.txt b/2024/haskell/resources/day6.txt new file mode 100644 index 0000000..2da6b30 --- /dev/null +++ b/2024/haskell/resources/day6.txt @@ -0,0 +1,130 @@ +......#........#.............#.##..........................................#.......#...#........#......................#.......... +.......................#...#................................#..#.........................................#.....#.....#............ +.......................................#.................#..................#....#........................................#....... +.............#...................#.#...............................#....#....#.#.......................................#..#....... +...............................#........##.#..............................#..............................#..#...#..#.............. +........................#......................................................................................#..#............... +............................#..........#.......#...................#.....#..................#.....................#..##........... +......................................................##........................#..............#........#..............#..#...#... +............................#.............................................##..........................................#........... +..........#............#....................................#...........#......................................................#.. +....#......#.........................................#.......#...............................#..#.##..................#........#.. +........................#.#..........##.#..........#......#.......#............................................................#.. +..........................................................................................#.#..........................#.......... +.............................#............#.......................#................#....................................#......... +...................................#.........................#.............#......#...#................................#.....#.... +..........#..................#..#.....................#...#...#.........................................#................#........ +....#....#...........#...#..........................................#.............#..#......#................#.....#.............. +....................................................................................#......#....##..##....#....................... +...........................#......................#.........##................#............#.......................#...#.......... +...........................#....................#............................................#........#.........................#. +..#......#.......#.#...........................#......#....#.#...#.............................#............#..............#...... +.......#................#...................................#.........................#..................................#........ +..................................................................#...........................................................#... +......................#....#........................................................................................#............. +...#..................#.......#......................................................................#.#....................#..... +................#....................................#.........#..#.........................#...............#.......#............. +.......................................#.................#..................................#...#...........#..................... +....#.....###..................#........#...#..............#............#...............................................#......... +...................#.......................................................#...................................#.................. +....#......................................#...##.....#........#......#......#..........................................#......... +......................#............#...............#................#...............................#............................. +......................#..............................................#...........#............#.................................#. +#.#..............................#..#......#.............#.......#......................#...........#........#..........#......... +....#....#.......................................#.......................................................#........................ +.......#............................#...........................#.........................#...............#....................... +.....................................#........#.....#........#.......................#...............#..........................#. +....#.......................................#........#......................................................#.................#... +............#..............#...#.......#..#.................................................................................##...# +...#..................#...................#....#............................................................................#..... +.....#....................#...............#.............................................#.....#...............................#... +..............................#.......................#.................#.......................................................#. +.........#....................#..............................................................................#.................#.. +......#..................#.........................#.......#.....#...........#....#...................................#......#.... +.........#...#......................#......#.................#.........................................#...................#...... +....#....#.................................#..#..#........#............................................#.......#.................. +....................#...........................#...#............#...........................#.................................... +................#................#....#.......................................#....#..........#.#.#..........#.................... +....#............................#...................................#.....................................................#.#.... +....................................#............#......................#......................##.....................#.......#... +.........................#...................................#.....#................................................#............. +...........#.#..#............................................................................#.#.................................. +....#......#.#..................................................#..#....#...#..#...................................#.............. +#.........................#.#.................................................................#.#.............................#... +..................#...#........#.......................................................#....#..............................#...#.. +.........#..........#.............................................................................................#............... +....................................................................#.......................#..#............#............#........ +.................#.................#.............................................#..................................#............. +.#...................................................................................................#................#........... +...#....#.#.#.........#............#.............................................................................................. +..................#...#......................................#...#.............#....#....#................#....................... +.....#................................##....................................................................#..................... +............#..................#......#....................#.....#.#.........................##............#............#.......#. +............................#..#.................#.............................................#.................................. +............#...............#..........................................................#........#................................. +.......#.......#.......................................##..............##......................................................... +....................#.........#.....#..............#....#.......................................................#................. +...#............................................................#.............................................#...#............#.. +....#..............................#...............................#..........................................#................... +............................................................................................................#....................# +..#.............................................................................................................#............#.... +..........#...............#.........................................................#...........#................................. +...............#.....................#....................................#....................#.....#...#.....................#.. +.#......#.........................................................................................#..#............................ +......#..............#........#........#........#.........................................................#....................... +............................#...........#..#.............................................................................#........ +..................#..............#.......................................#.........#...............#.....................#.#...... +...........................................#.##................................................................................... +.......................#.............................................................................................#............ +..........#................................#......#..............................#.................#........#......#.#.........#.. +#.......#........................#.....#..........##......#................#......................................#..#..#......#.. +........................##........................#....................#......................................#.................#. +..........................#.#........................................................................................#............ +..........#.........#.....#......#............#..#................................................##.................#............ +........#.....#............##...........................................#..#...............................................#.....# +..............#.......#......................#.....#.......................#.........#........#.................#...#....#........ +..............#.................................#.................................................##.............................. +................................#........#...........#........................................................#................... +..#.#..................#....#......#..............................#.....#....#.#.............#...............................#.... +.....................................................................#......#.........#.......#.........................#....#..#. +.#..........................#.....#...........................................##..^.#..........................#....#....#....#... +...........................#..#................................................................#...#........#.........#........... +......#.................#..............#................#.........#........................#..#........#......#................... +.....#..................#..........#............................................................................#.#...........#... +..........#.........#.................................#......#....#...............#.....................#...#..................... +...........#.......#...........#..#...............#...#..............#...........................................#................ +..............................................................#................................................................... +................#..............#.....................#.......#.....................................................#.............. +#................#.......#.#..............................#..........................#.............................#..........#... +.#...#.........##..........#......................#....#.........#....................#...............................#.....#..... +....#......#.................#....................................#............................................................... +......#..........#...............................................................#....#...............#.....#.##.................. +............................................................#..................#..#...................#.....#..................... +......................#.......#...#....#....................................#.............................#............#.......... +.#.............#.....................#...............#.......#...............##.....#..................##...#..................... +........#........................................................###.#..........................................#................. +...##.#................................................................................................#.......................... +.............##................#.............#....................#....#......................#........................#.....#.... +..#.......#............................................#...............................................#.......................... +.................#....#.......................................................#............#..#........................#.......#.# +...#..#......................#............#........#...........................................................................#.. +....................................#.......................#.....................................#.....#..#...................... +.#...............#......#...........#.....#........##....#.......#.....#...................................................#...... +...................#...#............................#..##........#...........................#...........#........................ +....................#.#.....................................................................................#......#.............. +....#...........#....#...#...#.....................#............................................#..............#.................. +......#.#......#................#......................................#...............#.......................................... +.......#.#................#..............#.....................#.#......#..................#...................................... +.....#................................#..............#.......#......##........#................................#..........#....... +.....................................#......#.........#...#.....#..........#..........................#........................... +......#.......#............................................................#..#....................#...............#.........#.... +.........................#...........#.............#......#..#..............................................................#..... +.........#.......##.....#....................................#.....#..............#......#.......#..................##.........#.. +.........................#...................#...#.....#...........................................#.................#..#......... +...........#..........#.......................................................................................................#..# +.....#................................................#...........................................................#....#.......... +..............#.................................#.............#.........................................................#......... +............#.........................................................#.....#...............................................#..... +..................................................#.................#.............................#....#...#.........#.......#.... +........#................#................................................................#................#....................#. +..................##............................###.........#.......#................#........#......#............#............... diff --git a/2024/haskell/resources/day6_example.txt b/2024/haskell/resources/day6_example.txt new file mode 100644 index 0000000..a4eb402 --- /dev/null +++ b/2024/haskell/resources/day6_example.txt @@ -0,0 +1,10 @@ +....#..... +.........# +.......... +..#....... +.......#.. +.......... +.#..^..... +........#. +#......... +......#...