Add solution to day 5.

This commit is contained in:
Hans Goor 2025-12-07 22:42:06 +01:00
parent 22207e0791
commit 0b525ccb1f
Signed by: eyedevelop
SSH key fingerprint: SHA256:Td89veptDEwCV8J3fjqnknNk7SbwzedYhauyC2nFBYg
5 changed files with 1282 additions and 0 deletions

View file

@ -93,6 +93,20 @@ executable day4
, base >=4.7 && <5 , base >=4.7 && <5
default-language: Haskell2010 default-language: Haskell2010
executable day5
main-is: Main.hs
other-modules:
Paths_aoc
autogen-modules:
Paths_aoc
hs-source-dirs:
app/day5
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:
aoc
, base >=4.7 && <5
default-language: Haskell2010
test-suite aoc-test test-suite aoc-test
type: exitcode-stdio-1.0 type: exitcode-stdio-1.0
main-is: Spec.hs main-is: Spec.hs

75
2025/aoc/app/day5/Main.hs Normal file
View file

@ -0,0 +1,75 @@
module Main (main) where
import Data.List (isPrefixOf, sort)
type Range = (Int, Int)
type FreshDatabase = [Range]
takeWhileList :: ([a] -> Bool) -> [a] -> [a]
takeWhileList _ [] = []
takeWhileList f (x : xs)
| f (x : xs) = x : takeWhileList f xs
| otherwise = []
splitOn :: (Eq a) => [a] -> [a] -> [[a]]
splitOn x [] = []
splitOn x xs =
let e = takeWhileList (not . isPrefixOf x) xs
in e : splitOn x (drop (length e + length x) xs)
processRange :: String -> Range
processRange s =
case splitOn "-" s of
[a, b] -> (read a :: Int, read b :: Int)
_ -> error "Invalid range!"
isFresh :: FreshDatabase -> Int -> Bool
isFresh [] _ = False
isFresh ((start, end) : xs) v = start <= v && v <= end || isFresh xs v
buildDatabase :: String -> FreshDatabase -> FreshDatabase
buildDatabase range db = processRange range : db
freshIngredients :: FreshDatabase -> [Int] -> [Int]
freshIngredients db = filter (isFresh db)
parseDatabase :: String -> FreshDatabase
parseDatabase = foldr buildDatabase [] . lines
parseIngredients :: String -> [Int]
parseIngredients = map (\x -> read x :: Int) . lines
parseInput :: [String] -> (FreshDatabase, [Int])
parseInput [a, b] = (parseDatabase a, parseIngredients b)
parseInput _ = error "Wrong input!"
part1 :: IO ()
part1 =
getContents
>>= print . length . uncurry freshIngredients . parseInput . splitOn "\n\n"
data RangeEvent = StartEvent | StopEvent deriving (Eq, Ord, Show)
rangeCoverage :: [Range] -> Int
rangeCoverage =
(\(_, _, _, c) -> c)
. foldl countCoverage (0, 0, 0, 0)
. sort
. concatMap (\(s, e) -> [(s, StartEvent), (e, StopEvent)])
where
countCoverage :: (Int, Int, Int, Int) -> (Int, RangeEvent) -> (Int, Int, Int, Int)
countCoverage (_, lastEnd, 0, coverage) (start, StartEvent)
| start == lastEnd = (start + 1, lastEnd, 1, coverage)
| otherwise = (start, lastEnd, 1, coverage)
countCoverage (lastStart, lastEnd, n, coverage) (_, StartEvent) = (lastStart, lastEnd, n + 1, coverage)
countCoverage (lastStart, _, 1, coverage) (end, StopEvent) = (lastStart, end, 0, coverage + ((end + 1) - lastStart))
countCoverage (lastStart, lastEnd, n, coverage) (_, StopEvent) = (lastStart, lastEnd, n - 1, coverage)
part2 :: IO ()
part2 =
getContents
>>= print . rangeCoverage . fst . parseInput . splitOn "\n\n"
main :: IO ()
main = part2

1173
2025/aoc/inputs/day5.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,11 @@
3-5
10-14
16-20
12-18
1
5
8
11
17
32

View file

@ -73,6 +73,15 @@ executables:
- -with-rtsopts=-N - -with-rtsopts=-N
dependencies: dependencies:
- aoc - aoc
day5:
main: Main.hs
source-dirs: app/day5
ghc-options:
- -threaded
- -rtsopts
- -with-rtsopts=-N
dependencies:
- aoc
tests: tests:
aoc-test: aoc-test: