summaryrefslogblamecommitdiffstats
path: root/src/day13.exs
blob: 4dca20a3eea56cc8ab48edcaa936bf19ac9749be (plain) (tree)




























































                                                                  
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}")