This commit is contained in:
2023-12-05 10:48:55 +01:00
parent 53cad097f8
commit 0ead7dd768
5 changed files with 126 additions and 0 deletions

55
day05/Commons.hs Normal file
View File

@@ -0,0 +1,55 @@
module Commons where
import Data.List.Utils (split)
import GHC.IO.Handle (isEOF)
data ConversionEntry = ConversionEntry { sourceStart :: Int, destinationStart :: Int, size :: Int } deriving Show
type ConversionMap = [ConversionEntry]
data Almanac = Almanac { seeds :: [Int], toSoil :: ConversionMap, toFertilizer :: ConversionMap,
toWater :: ConversionMap, toLight :: ConversionMap, toTemperature :: ConversionMap,
toHumidity :: ConversionMap, toLocation :: ConversionMap } deriving Show
parseSeeds :: [String] -> [Int]
parseSeeds = map read
parseSeedsRaw :: IO [Int]
parseSeedsRaw = do line <- getLine
getLine
let seeds = parseSeeds $ tail $ split " " line
return seeds
parseConversionEntry :: [String] -> ConversionEntry
parseConversionEntry (ds: ss: size: _) = ConversionEntry {sourceStart = read ss, destinationStart = read ds,
size = read size}
parseConversionMapRaw :: IO ConversionMap
parseConversionMapRaw = do done <- isEOF
if done
then return []
else do line <- getLine
case line of
[] -> do return []
_ -> do let eMap = parseConversionEntry $ split " " line
othersEMap <- parseConversionMapRaw
return $ eMap: othersEMap
parse :: IO Almanac
parse = do seeds <- parseSeedsRaw
getLine
toSoil <- parseConversionMapRaw
getLine
toFertilizer <- parseConversionMapRaw
getLine
toWater <- parseConversionMapRaw
getLine
toLight <- parseConversionMapRaw
getLine
toTemperature <- parseConversionMapRaw
getLine
toHumidity <- parseConversionMapRaw
getLine
toLocation <- parseConversionMapRaw
return Almanac {seeds = seeds, toSoil = toSoil, toFertilizer = toFertilizer, toWater = toWater,
toLight = toLight, toTemperature = toTemperature, toHumidity = toHumidity,
toLocation = toLocation}

12
day05/Main.hs Normal file
View File

@@ -0,0 +1,12 @@
module Main where
import Commons
import qualified Part1
import qualified Part2
main = do almanac <- parse
let part1Res = minimum $ Part1.getLocations almanac
print part1Res
let part2Res = minimum $ Part2.getLocationsStarts almanac
print part2Res

18
day05/Part1.hs Normal file
View File

@@ -0,0 +1,18 @@
module Part1 where
import Commons
applyConversionMap :: ConversionMap -> Int -> Int
applyConversionMap [] v = v
applyConversionMap (e: t) v | v >= sourceStart e && v <= sourceStart e + size e = destinationStart e - sourceStart e + v
| otherwise = applyConversionMap t v
applyConversionMapToList :: ConversionMap -> [Int] -> [Int]
applyConversionMapToList cm = map $ applyConversionMap cm
getLocations :: Almanac -> [Int]
getLocations a = applyConversionMapToList (toLocation a) . applyConversionMapToList (toHumidity a)
. applyConversionMapToList (toTemperature a) . applyConversionMapToList (toLight a)
. applyConversionMapToList (toWater a) . applyConversionMapToList (toFertilizer a)
. applyConversionMapToList (toSoil a) $ seeds a

33
day05/Part2.hs Normal file
View File

@@ -0,0 +1,33 @@
module Part2 where
import Commons
applyConversionMap :: ConversionMap -> Int -> Int -> [Int]
applyConversionMap [] v vs = [v, vs]
applyConversionMap _ _ 0 = []
applyConversionMap (e: t) v vs
| v >= sourceStart e && v <= sourceStart e + size e =
let newVs = min (sourceStart e + size e) (v + vs) - v
in (destinationStart e - sourceStart e + v): newVs: applyConversionMap t (v + newVs) (vs - newVs)
| v < sourceStart e && v + vs >= sourceStart e =
let newVs = v + vs - sourceStart e
in applyConversionMap (e: t) (sourceStart e) newVs ++ applyConversionMap t v (vs - newVs)
| otherwise = applyConversionMap t v vs
applyConversionMapToList :: ConversionMap -> [Int] -> [Int]
applyConversionMapToList cm [] = []
applyConversionMapToList cm (v: vs: t) = applyConversionMap cm v vs ++ applyConversionMapToList cm t
getLocations :: Almanac -> [Int]
getLocations a = applyConversionMapToList (toLocation a) . applyConversionMapToList (toHumidity a)
. applyConversionMapToList (toTemperature a) . applyConversionMapToList (toLight a)
. applyConversionMapToList (toWater a) . applyConversionMapToList (toFertilizer a)
. applyConversionMapToList (toSoil a) $ seeds a
dropLocationsSizes :: [Int] -> [Int]
dropLocationsSizes [] = []
dropLocationsSizes (start: size: t) = start: dropLocationsSizes t
getLocationsStarts :: Almanac -> [Int]
getLocationsStarts = dropLocationsSizes . getLocations