Add solution to day 5.
This commit is contained in:
parent
22207e0791
commit
0b525ccb1f
5 changed files with 1282 additions and 0 deletions
|
|
@ -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
75
2025/aoc/app/day5/Main.hs
Normal 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
1173
2025/aoc/inputs/day5.txt
Normal file
File diff suppressed because it is too large
Load diff
11
2025/aoc/inputs/day5_test.txt
Normal file
11
2025/aoc/inputs/day5_test.txt
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
3-5
|
||||||
|
10-14
|
||||||
|
16-20
|
||||||
|
12-18
|
||||||
|
|
||||||
|
1
|
||||||
|
5
|
||||||
|
8
|
||||||
|
11
|
||||||
|
17
|
||||||
|
32
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue