2025 day 7 part 2 in Haskell

This commit is contained in:
2025-12-07 16:51:24 +01:00
parent 29e02c819e
commit a737a35227
2 changed files with 39 additions and 10 deletions

View File

@@ -6,7 +6,7 @@ test: solve
./solve sample.txt ./solve sample.txt
solve: solve.hs solve: solve.hs
ghc -dynamic -O -o $@ $^ ghc -dynamic -O -g -o $@ $^
clean: clean:
$(RM) solve $(RM) solve

View File

@@ -1,4 +1,3 @@
import Basement.Compat.IsList qualified as Set
import Data.Array import Data.Array
import Data.List import Data.List
import Data.Maybe import Data.Maybe
@@ -6,29 +5,59 @@ import Data.Set
import System.Environment import System.Environment
import System.Exit import System.Exit
main = getArgs >>= parse >>= (print . solve . lines) main = getArgs >>= parse >>= run
findStartingPoint line = fromJust (elemIndex 'S' line)
solve lines = simulate (tail lines) 0 (Data.Set.singleton (findStartingPoint (head lines)))
stringToArray :: [Char] -> Array Int Char stringToArray :: [Char] -> Array Int Char
stringToArray s = listArray (0, length s - 1) s stringToArray s = listArray (0, length s - 1) s
run :: String -> IO ()
run input =
let gridLines = lines input
startingPoint = findStartingPoint (head gridLines)
initial = Data.Set.singleton startingPoint
arrLines = Data.List.map stringToArray (tail gridLines)
in do
print (part1 arrLines startingPoint)
print (part2 arrLines startingPoint)
findStartingPoint :: [Char] -> Int
findStartingPoint line = fromJust (elemIndex 'S' line)
part1 arrLines startingPoint =
let initial = Data.Set.singleton startingPoint
in simulate arrLines 0 initial
checkHit :: Array Int Char -> Int -> [Int] checkHit :: Array Int Char -> Int -> [Int]
checkHit line idx = case line ! idx of checkHit line idx = case line ! idx of
'^' -> (idx - 1) : [idx + 1] '^' -> (idx - 1) : [idx + 1]
_ -> [idx] _ -> [idx]
simulate :: [[Char]] -> Int -> Set Int -> Int
simulate [] count active = count simulate [] count active = count
simulate lines count active = simulate lines count active =
let arr = stringToArray (head lines) let arr = head lines
followUp = Data.Set.fromList $ concatMap (checkHit arr) (Set.toList active) followUp = Data.Set.fromList $ concatMap (checkHit arr) (Data.Set.toList active)
hits = length (Data.Set.filter (\i -> arr ! i == '^') active) hits = length (Data.Set.filter (\i -> arr ! i == '^') active)
remainder = tail lines remainder = tail lines
in simulate remainder (hits + count) followUp in simulate remainder (hits + count) followUp
part2 :: [Array Int Char] -> Int -> Int
part2 arrLines startingPosition =
let n = length arrLines
arr = listArray (0, n - 1) arrLines
width = length $ head arrLines
compute i pos
| i >= n = 1
| otherwise =
let line = arr ! i
in case line ! pos of
'^' -> memo ! (i + 1, pos - 1) + memo ! (i + 1, pos + 1)
_ -> memo ! (i + 1, pos)
memo =
array
((0, 0), (n, width - 1))
[((i, pos), compute i pos) | i <- [0 .. n], pos <- [0 .. width - 1]]
in memo ! (0, startingPosition)
parse ["-h"] = usage >> exitSuccess parse ["-h"] = usage >> exitSuccess
parse [] = usage >> die usageStr parse [] = usage >> die usageStr
parse fs = concat `fmap` mapM readFile fs parse fs = concat `fmap` mapM readFile fs