adventofcode/2023/app/Day5.hs

63 lines
1.7 KiB
Haskell
Raw Normal View History

2023-12-05 23:49:36 +01:00
module Day5 where
import System.IO
import ParseLib.Abstract
import Prelude hiding ((<*), (*>))
import Data.Char
import Data.List
import Data.Maybe
type Input = Int
type Output = Int
type Length = Int
data Range = Range Output Input Length deriving Show
type From = String
type To = String
data Map = Map From To [Range] deriving Show
main :: IO ()
main = do
handle <- openFile "app/Day5-input.txt" ReadMode
input <- hGetContents handle
let (seeds, maps) = fst $ head $ parse parseInput input
locations = map (applyTill maps "seed" "location") seeds
putStr "Part 1: "
print $ minimum locations
let seeds' = concatMap range (pairs seeds)
locations' = map (applyTill maps "seed" "location") seeds'
putStr "Part 2: "
print $ minimum locations'
pure ()
whitespace = greedy (satisfy isSpace)
number = whitespace *> natural
parseInput = (,) <$> parseHeader <*> greedy parseMap
parseHeader = token "seeds: " *> greedy number <* whitespace
parseMap = Map <$> identifier <* token "-to-" <*> identifier <* token " map:\n" <*> greedy parseRange <* whitespace
parseRange = Range <$> number <*> number <*> number <* whitespace
apply :: [Map] -> From -> Input -> (To, Output)
apply ms f i = (t, applyMap m i)
where
m@(Map _ t _) = fromJust $ find (\(Map f' _ _) -> f' == f) ms
applyMap :: Map -> Input -> Output
applyMap (Map _ _ []) i' = i'
applyMap (Map f t ((Range o i l):rs)) i'
| i <= i' && i' <= i+l = o + (i' - i)
| otherwise = applyMap (Map f t rs) i'
applyTill :: [Map] -> From -> To -> Input -> Output
applyTill ms f t i | t == t' = o
| otherwise = applyTill ms t' t o
where (t', o) = apply ms f i
pairs [] = []
pairs (x1:x2:xs) = (x1,x2) : pairs xs
range (x,y) = [x..x+y-1]