X-Git-Url: https://git.njae.me.uk/?p=advent-of-code-19.git;a=blobdiff_plain;f=advent14%2Fsrc%2Fadvent14.hs;fp=advent14%2Fsrc%2Fadvent14.hs;h=4e35ee25605fa687e24bf65f88f219f912862f42;hp=1fafe9bce157c425d898d3099832e89265e4ed1d;hb=0cb8ce8d9c118041a6095764fe2672b2f67879ba;hpb=7d375e7c856ef4f6235e9096edd13e871f2229e6 diff --git a/advent14/src/advent14.hs b/advent14/src/advent14.hs index 1fafe9b..4e35ee2 100644 --- a/advent14/src/advent14.hs +++ b/advent14/src/advent14.hs @@ -17,75 +17,66 @@ import qualified Data.Set as S data Reagent = Reagent { _quantity :: Int, _chemical :: String } deriving (Ord, Eq, Show) -data Rule = Rule {_lhs :: S.Set Reagent, _rhs :: Reagent} deriving (Eq, Show) +data Reaction = Reaction {_lhs :: S.Set Reagent, _rhs :: Reagent} deriving (Eq, Show) -type RuleBase = M.Map String Rule +type Reactions = M.Map String Reaction type Requirement = M.Map String Int main :: IO () main = do text <- TIO.readFile "data/advent14.txt" - -- let rules = successfulParse text - -- let ruleBase = mkRuleBase rules - let ruleBase = successfulParse text - -- print rules - -- print ruleBase - print $ part1 ruleBase - print $ part2 ruleBase + let reactions = successfulParse text + print $ part1 reactions + print $ part2 reactions oreLimit :: Int oreLimit = 10^12 -mkRuleBase :: [Rule] -> RuleBase -mkRuleBase = foldl' addRule M.empty - where addRule base rule = M.insert (_chemical $ _rhs rule) rule base - - --- part1 rules = required!"ORE" +-- part1 reactions = required!"ORE" -- where required0 = M.singleton "FUEL" 1 --- required = produce rules required -part1 rules = oreForFuel rules 1 +-- required = produce reactions required +part1 reactions = oreForFuel reactions 1 -part2 rules = searchFuel rules (upper `div` 2) upper - where upper = findUpper rules (oreLimit `div` base) - base = oreForFuel rules 1 +part2 reactions = searchFuel reactions (upper `div` 2) upper + where upper = findUpper reactions (oreLimit `div` base) + base = oreForFuel reactions 1 -oreForFuel :: RuleBase -> Int -> Int -oreForFuel rules n = required!"ORE" +oreForFuel :: Reactions -> Int -> Int +oreForFuel reactions n = required!"ORE" where required0 = M.singleton "FUEL" n - required = produce rules required0 + required = produce reactions required0 -findUpper :: RuleBase -> Int -> Int +findUpper :: Reactions -> Int -> Int -- findUpper _ n | trace ("Upper " ++ show n) False = undefined -findUpper rules n = if ore > oreLimit +findUpper reactions n = if ore > oreLimit then n - else findUpper rules (n * 2) - where ore = oreForFuel rules n + else findUpper reactions (n * 2) + where ore = oreForFuel reactions n -searchFuel :: RuleBase -> Int -> Int -> Int +searchFuel :: Reactions -> Int -> Int -> Int -- searchFuel _ lower upper | trace ("Search " ++ show lower ++ " - " ++ show upper) False = undefined -searchFuel rules lower upper +searchFuel reactions lower upper | upper == lower = upper | otherwise = if ore > oreLimit - then searchFuel rules lower (mid - 1) - else searchFuel rules mid upper + then searchFuel reactions lower (mid - 1) + else searchFuel reactions mid upper where mid = (upper + lower + 1) `div` 2 - ore = oreForFuel rules mid + ore = oreForFuel reactions mid -produce :: RuleBase -> Requirement -> Requirement -produce rules required +produce :: Reactions -> Requirement -> Requirement +produce reactions required | M.null outstanding = required - | otherwise = produce rules required'' + | otherwise = produce reactions required'' where outstanding = M.filter (> 0) $ nonOre required (chem, qty) = M.findMin outstanding - rule = rules!chem - productQty = _quantity $ _rhs rule + reaction = reactions!chem + productQty = _quantity $ _rhs reaction applications = max 1 (qty `div` productQty) qty' = qty - (applications * productQty) required' = M.insert chem qty' required - required'' = S.foldl (addRequrirement applications) required' (_lhs rule) + required'' = S.foldl (addRequrirement applications) required' (_lhs reaction) nonOre :: Requirement -> Requirement @@ -114,16 +105,20 @@ arrowP = symb "=>" commaP = symb "," identifierP = some alphaNumChar <* sc -rulesP = mkRuleBase <$> many ruleP +reactionsP = mkReactions <$> many reactionP -ruleP = Rule <$> reagentsP <* arrowP <*> reagentP +reactionP = Reaction <$> reagentsP <* arrowP <*> reagentP reagentP = Reagent <$> integer <*> identifierP reagentsP = S.fromList <$> reagentP `sepBy` commaP +mkReactions :: [Reaction] -> Reactions +mkReactions = foldl' addReaction M.empty + where addReaction base reaction = M.insert (_chemical $ _rhs reaction) reaction base + -- successfulParse :: Text -> [Vec] -successfulParse :: Text -> RuleBase +successfulParse :: Text -> Reactions successfulParse input = - case parse rulesP "input" input of + case parse reactionsP "input" input of Left _err -> M.empty -- TIO.putStr $ T.pack $ parseErrorPretty err - Right rules -> rules + Right reactions -> reactions