Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

🎄 Year 2024 🔔 Day 13

elixir/notebooks/2024/day13.livemd

🎄 Year 2024 🔔 Day 13

Setup

matrices =
  File.read!("#{__DIR__}/../../../inputs/2024/day13.txt")
  |> String.split("\n\n", trim: true)
  |> Enum.map(fn input ->
    [
      "Button A: " <> button_a,
      "Button B: " <> button_b,
      "Prize: " <> target
    ] = String.split(input, "\n", trim: true)

    matcher_regex = ~r/X\+?=?(\d+), Y\+?=?(\d+)/

    [ax, ay] =
      Regex.run(matcher_regex, button_a, capture: :all_but_first)
      |> Enum.map(&amp;String.to_integer/1)

    [bx, by] =
      Regex.run(matcher_regex, button_b, capture: :all_but_first)
      |> Enum.map(&amp;String.to_integer/1)

    [xt, yt] =
      Regex.run(matcher_regex, target, capture: :all_but_first)
      |> Enum.map(&amp;String.to_integer/1)

    [
      [ax, bx, xt],
      [ay, by, yt]
    ]
  end)

Part 1

matrices
# Gaussian elimination ignoring integer division remainders
|> Enum.map(fn original = [[ax, bx, xt], [ay, by, yt]] ->
  [0, by, yt] = [ay * ax - ax * ay, by * ax - bx * ay, yt * ax - xt * ay]
  br = div(yt, by)
  ar = div(xt - bx * br, ax)

  {original, {ar, br}}
end)
|> Enum.filter(fn {[[ax, bx, xt], [ay, by, yt]], {ar, br}} ->
  solution_in_bound = ar >= 0 &amp;&amp; br >= 0 &amp;&amp; ar <= 100 &amp;&amp; br <= 100
  # since remainders are ignored make sure the result works
  solution_correct = ax * ar + bx * br == xt &amp;&amp; ay * ar + by * br == yt

  solution_in_bound &amp;&amp; solution_correct
end)
|> Enum.map(fn {_, {ar, br}} -> ar * 3 + br end)
|> Enum.sum()

Part 2

matrices
|> Enum.map(fn [[ax, bx, xt], [ay, by, yt]] ->
  add_to_target = 10_000_000_000_000
  [[ax, bx, xt + add_to_target], [ay, by, yt + add_to_target]]
end)
# Gaussian elimination ignoring integer division remainders
|> Enum.map(fn original = [[ax, bx, xt], [ay, by, yt]] ->
  [0, by, yt] = [ay * ax - ax * ay, by * ax - bx * ay, yt * ax - xt * ay]
  br = div(yt, by)
  ar = div(xt - bx * br, ax)

  {original, {ar, br}}
end)
|> Enum.filter(fn {[[ax, bx, xt], [ay, by, yt]], {ar, br}} ->
  solution_in_bound = ar >= 0 &amp;&amp; br >= 0
  # since remainders are ignored make sure the result works
  solution_correct = ax * ar + bx * br == xt &amp;&amp; ay * ar + by * br == yt

  solution_in_bound &amp;&amp; solution_correct
end)
|> Enum.map(fn {_, {ar, br}} -> ar * 3 + br end)
|> Enum.sum()