defmodule Day13 do defmodule Game do @derive Inspect defstruct [:a, :b, :prize] def from_data(data, extra \\ 0) do Regex.scan(~r/\d+/, data) |> Enum.map(&String.to_integer(hd(&1))) |> Enum.chunk_every(2) |> Enum.map(&List.to_tuple/1) |> then(fn [a, b, prize] -> %Game{ a: a, b: b, prize: {elem(prize, 0) + extra, elem(prize, 1) + extra}, } end) end def cheapest(game) do cheapest(game.a, game.b, game.prize) end defp cheapest({a1, a2}, {b1, b2}, {s1, s2}) do c = s2*a1 - a2*s1 d = a1*b2 - a2*b1 if rem(c, d) == 0 do y = div(c, d) e = s1 - b1 * y f = a1 if rem(e, f) == 0 do x = div(e, f) x*3 + y end end end end def part1(data, extra \\ 0) do data |> String.split("\n\n", trim: true) |> Enum.map(&Game.from_data(&1, extra)) |> Enum.map(&Game.cheapest/1) |> Enum.reject(& &1 == nil) |> Enum.sum() end def part2(data) do part1(data, 10000000000000) end end data = IO.read(:stdio, :eof) {time1 , ans1} = :timer.tc(fn -> Day13.part1(data) end) IO.puts("Time : #{time1 / 1000000}") IO.puts("Answer: #{ans1}") {time2 , ans2} = :timer.tc(fn -> Day13.part2(data) end) IO.puts("Time : #{time2 / 1000000}") IO.puts("Answer: #{ans2}")