aoc

Advent of Code Solutions
git clone git://git.alexkarle.com.com/aoc
Log | Files | Refs | README | LICENSE

commit 3d1d1df937b997715071049f4597afcaf5067a1e (patch)
parent 7bf24fbbdb625de98ac2ff4dc5fd068b8f732d71
Author: Alex Karle <alex@alexkarle.com>
Date:   Sat, 14 Dec 2024 03:20:53 +0100

2024: Add day 13

Fun revisiting linear equations :)

Diffstat:
A2024/13/1.py | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
A2024/13/2.py | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/2024/13/1.py b/2024/13/1.py @@ -0,0 +1,51 @@ +#!/usr/bin/env python3 +import sys +import re + +buta_re = re.compile("Button A: X\+(\d+), Y\+(\d+)") +butb_re = re.compile("Button B: X\+(\d+), Y\+(\d+)") +priz_re = re.compile("Prize: X=(\d+), Y=(\d+)") + +def parse(): + games = [] + game = {} + for l in sys.stdin: + am = buta_re.match(l) + bm = butb_re.match(l) + pm = priz_re.match(l) + if am: + game["A"] = [int(x) for x in am.groups(1)] + elif bm: + game["B"] = [int(x) for x in bm.groups(1)] + elif pm: + game["P"] = [int(x) for x in pm.groups(1)] + else: + games.append(game) + game = {} + if game: + games.append(game) + return games + +# Its a linear equation, so they should interesect exactly +# once, not at all, or continuously (same line). +# Searching the entire b space first (inner loop) gives +# us the cheapest if they're the same line +# +# For pt 1, we just brute force it rather than solve it +def solve(game): + for a in range(101): + for b in range(101): + if a * game['A'][0] + b * game['B'][0] == game['P'][0]: + if a * game['A'][1] + b * game['B'][1] == game['P'][1]: + return (a, b) + return None + + +if __name__ == '__main__': + tot = 0 + games = parse() + for g in games: + sol = solve(g) + if sol is not None: + tot += sol[0] * 3 + sol[1] + print(tot) diff --git a/2024/13/2.py b/2024/13/2.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +import sys +import re + +buta_re = re.compile("Button A: X\+(\d+), Y\+(\d+)") +butb_re = re.compile("Button B: X\+(\d+), Y\+(\d+)") +priz_re = re.compile("Prize: X=(\d+), Y=(\d+)") + +def parse(): + games = [] + game = {} + for l in sys.stdin: + am = buta_re.match(l) + bm = butb_re.match(l) + pm = priz_re.match(l) + if am: + game["A"] = [int(x) for x in am.groups(1)] + elif bm: + game["B"] = [int(x) for x in bm.groups(1)] + elif pm: + game["P"] = [int(x) + 10000000000000 for x in pm.groups(1)] + else: + games.append(game) + game = {} + if game: + games.append(game) + return games + +# Its a linear equation, so they should interesect exactly +# once, not at all, or continuously (same line). +# +# For pt 2, we can't brute force--have to solve it! +# +# 94a + 22b = 8400 +# 34a + 67b = 5400 +# +# P1 = A1a + B1b -> a = (P1 - B1b)/A1 = P1A2 - B1A2b +# P2 = A2a + B2b -> a = (P2 - B2b)/A2 = P2A1 - B2A1b +# +# P1A2 - B1A2b = P2A1 - B2A1b +# P1A2 - P2A1 = B1A2b - B2A1b +# b = (P1A2 - P2A1) / (B1A2 - B2A1) +def solve(game): + P1, P2 = game['P'] + A1, A2 = game['A'] + B1, B2 = game['B'] + b = (P1 * A2 - P2 * A1) / (B1 * A2 - B2 * A1) + a = (P1 - B1 * b) / A1 + if b != int(b) or b < 0 or a != int(a) or a < 0: + return None + return (a, b) + + +if __name__ == '__main__': + tot = 0 + games = parse() + for g in games: + sol = solve(g) + if sol is not None: + tot += sol[0] * 3 + sol[1] + print(tot)