Advent of Code 2024
Mix.install([
{:req, "~> 0.5.8"},
{:kino, "~> 0.14.2"}
])
Day 13
Kino.configure(inspect: [charlists: :as_lists])
input =
"https://adventofcode.com/2024/day/13/input"
|> Req.get!(headers: [cookie: "session=#{System.get_env("AOC_COOKIE")}"])
|> Map.get(:body)
sample =
"""
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400
Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176
Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450
Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279
"""
defmodule Day13 do
def parse(input) do
input
|> String.split("\n\n", trim: true)
|> Enum.map(fn lines ->
lines
|> String.split("\n", trim: true)
|> Enum.map(fn s ->
[_, _, a, _, b] = Regex.run(~r/X(\+|=)(\d+), Y(\+|=)(\d+)/, s)
[a, b]
|> Enum.map(&String.to_integer/1)
|> List.to_tuple()
end)
end)
end
def cheapest_prize({ax, ay}, {bx, by}, {gx, gy}) do
# n * ax + m * bx = gx
# n * ay + m * by = gy
# use maths to eliminate one of the variables (n or m)
#
# let's remove m
# multiply by by: by * n * ax + m * bx * by = gx * by
# multiply by bx: bx * n * ay + m * bx * by = gy * bx
#
# then subtract the equations
# by * n * ax - bx * n * ay = gx * by - gy * bx
#
# extract n
# n * (by * ax - bx * ay) = gx * by - gy * bx
#
# solve for n
# n = (gx * by - gy * bx) / (by * ax - bx * ay)
a = (gx * by - gy * bx) / (by * ax - bx * ay)
# solve for m by substituting n
# m = (gx - n * ax) / bx
b = (gx - a * ax) / bx
# if we have integers, we have a solution
if trunc(a) == a && trunc(b) == b do
3 * trunc(a) + trunc(b)
else
0
end
end
def fewest_tokens(machines, addend \\ 0) do
machines
|> Enum.map(fn [{ax, ay}, {bx, by}, {gx, gy}] ->
cheapest_prize({ax, ay}, {bx, by}, {gx + addend, gy + addend})
end)
|> Enum.sum()
end
end
import Day13
Part 1
input
|> parse()
|> fewest_tokens()
Part 2
input
|> parse()
|> fewest_tokens(10000000000000)