diff --git a/2023/day02.nim b/2023/day02.nim index 93d4924..552871e 100644 --- a/2023/day02.nim +++ b/2023/day02.nim @@ -1,34 +1,49 @@ import std/strscans import std/strutils +type Turn = object + r, g, b: int + +func parseTurn(text: string): Turn = + for count in text.split(","): + let parts = count.strip.split() + case parts[1]: + of "red": (result.r = parts[0].parseInt) + of "green": (result.g = parts[0].parseInt) + of "blue": (result.b = parts[0].parseInt) + + +type Game = object + id: int + turns: seq[Turn] + +func parseGame(line: string): Game = + var rest: string + + if not scanf(line, "Game $i: $*$.", result.id, rest): + raise newException(ValueError, line) + + for turn in rest.split(";"): + result.turns.add(parseTurn(turn)) + +type Bag = object + r, g, b: int + proc part1(): int = let f = open("input/day02.txt") defer: f.close() - let - reds = 12 - greens = 13 - blues = 14 + let bag = Bag(r: 12, g: 13, b: 14) var line: string while f.readLine(line): - var id: int - var rest: string - - block game: - if not scanf(line, "Game $i: $*$.", id, rest): - echo "ERROR" - continue - - for counts in rest.split(";"): - var r, g, b: int - for s in counts.split(","): - let parts = s.strip.split() - case parts[1]: - of "red": (if parts[0].parseInt > reds: break game) - of "green": (if parts[0].parseInt > greens: break game) - of "blue": (if parts[0].parseInt > blues: break game) - inc result, id + block current: + let game = parseGame(line) + for turn in game.turns: + if turn.r > bag.r: break current + if turn.g > bag.g: break current + if turn.b > bag.b: break current + inc result, game.id proc part2(): int = let f = open("input/day02.txt") @@ -36,25 +51,15 @@ proc part2(): int = var line: string while f.readLine(line): - var id: int - var rest: string + var bag: Bag - if not scanf(line, "Game $i: $*$.", id, rest): - echo "ERROR" - continue + let game = parseGame(line) + for turn in game.turns: + bag.r = max(bag.r, turn.r) + bag.g = max(bag.g, turn.g) + bag.b = max(bag.b, turn.b) - var reds, greens, blues: int - - for counts in rest.split(";"): - var r, g, b: int - for s in counts.split(","): - let parts = s.strip.split() - case parts[1]: - of "red": (reds = max(reds, parts[0].parseInt)) - of "green": (greens = max(greens, parts[0].parseInt)) - of "blue": (blues = max(blues, parts[0].parseInt)) - - let power = reds * greens * blues + let power = bag.r * bag.g * bag.b inc result, power echo part1()