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

Advent of Code 2024 - Day 13

2024/day-13.livemd

Advent of Code 2024 - Day 13

Mix.install([
  {:kino_aoc, "~> 0.1.7"},
  {:nx, "~> 0.9.2"}
])

Input Parsing

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "13", System.fetch_env!("LB_AOC_SESSION"))
IO.puts(puzzle_input)
machines =
  ~r/(?:\+|\-)?\d+/
  |> Regex.scan(puzzle_input)
  |> List.flatten()
  |> Enum.map(&String.to_integer/1)
  |> Enum.chunk_every(6)
  |> Enum.map(fn [xa, ya, xb, yb, xt, yt] ->
    {
      {xa, ya},
      {xb, yb},
      {xt, yt}
    }
  end)
cost = fn machines ->
  for {{xa, ya}, {xb, yb}, {xt, yt}} <- machines do
    d = xb * ya - xa * yb
    
    if d == 0 do
      cost_a = rem(xt, xa) == 0 &amp;&amp; rem(yt, ya) == 0 &amp;&amp; (3 * div(yt, ya)) || nil
      cost_b = rem(xt, xb) == 0 &amp;&amp; rem(yt, yb) == 0 &amp;&amp; div(yt, yb) || nil
      min(cost_a, cost_b)
    else
      nx = xa * xb * yt - xa * xt * yb
      ny = xb * ya * yt - xt * ya * yb
  
      if rem(nx, d) == 0 and rem(ny, d) == 0 do
        y = div(ny, d)

        if rem(y, ya) == 0 and rem(yt - y, yb) == 0 do
          3 * div(y, ya) + div(yt - y, yb)
        else
          nil
        end
      else
        nil
      end
    end
  end
  |> Enum.reject(&amp;is_nil/1)
  |> Enum.sum()
end

Part 1

cost.(machines)

Part 2

offset = 10_000_000_000_000
machines
|> Enum.map(fn {a, b, {xt, yt}} ->
  {a, b, {xt + offset, yt + offset}}
end)
|> cost.()