diff --git a/README.md b/README.md index f01ef54..c849953 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ Thanks to Eric Wastl for creating this enjoyable event. Requires `lib.py` from [aocpy](https://git.felixm.de/felixm/aocpy) repository. +Requires `sympy` for day 24. + # Times @@ -40,6 +42,9 @@ Requires `lib.py` from [aocpy](https://git.felixm.de/felixm/aocpy) repository. something else before returning to the idea and it worked flawlessly. - Day 21: - Day 22: Not too hard, but definitely way too slow for leaderboard. -- Day 23: -- Day 24: +- Day 23: I found this fun because it required some creativity for part 2. Slow + af, of course. +- Day 24: Solve problem with sympy. I first used numpy to solve part 1 and it was + much faster than using sympy, but I lost that solution when switching to sympy. + Takes about three minutes to run for part 1 and then part 2 is under a second. - Day 25: diff --git a/d24.py b/d24.py new file mode 100644 index 0000000..ea69520 --- /dev/null +++ b/d24.py @@ -0,0 +1,74 @@ +from lib import * +import sympy as sp + +EXAMPLE = """19, 13, 30 @ -2, 1, -2 +18, 19, 22 @ -1, -1, -2 +20, 25, 34 @ -2, -2, -4 +12, 31, 28 @ -1, -2, -1 +20, 19, 15 @ 1, -5, -3 +""" + + +def solve1(input: Input): + if len(input.lines()) == 5: + lb = 7 + ub = 27 + else: + lb = 200000000000000 + ub = 400000000000000 + + # On paper: + # (px - sx1) / vx1 = (py - sy1) / vy1 + # (px - sx1) * vy1 = (py - sy1) * vx1 + # (px - sx1) * vy1 - (py - sy1) * vx1 = 0 + res = 0 + eqs = [str_to_ints(l) for l in input.lines()] + for i, eq1 in enumerate(eqs): + for eq2 in eqs[:i]: + sx1, sy1, _, vx1, vy1, _ = eq1 + sx2, sy2, _, vx2, vy2, _ = eq2 + + px, py = sp.symbols("px py") + es = [ + vy1 * (px - sx1) - vx1 * (py - sy1), + vy2 * (px - sx2) - vx2 * (py - sy2), + ] + r = sp.solve(es) + if not r: + continue + + x, y = r[px], r[py] + if lb <= x <= ub and lb <= y < ub: + t1 = (x - sx1) / vx1 + t2 = (x - sx2) / vx2 + if (t1 > 0 and t2 > 0): + res += 1 + + return res + + +def solve2(input: Input): + eqs = [str_to_ints(l) for l in input.lines()] + px, py, pz, vxo, vyo, vzo = sp.symbols("px py pz vxo vyo vzo") + es = [] + + # The first six equations are enough to find a solution for my problem set. + # Might have to be increased depending on input. + for i, (x, y, z, vx, vy, vz) in enumerate(eqs[:6]): + t = sp.symbols(f"t{i}") + es.append(px + vxo * t - x - vx * t) + es.append(py + vyo * t - y - vy * t) + es.append(pz + vzo * t - z - vz * t) + r = sp.solve(es)[0] + return r[px] + r[py] + r[pz] + +def main(): + DAY_INPUT = "i24.txt" + print("Solution 1:", solve1(Input(EXAMPLE))) + print("Solution 1:", solve1(Input(DAY_INPUT))) + print("Example 2:", solve2(Input(EXAMPLE))) + print("Solution 2:", solve2(Input(DAY_INPUT))) + return + +if __name__ == "__main__": + main()