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

Day 6

day6/sol.livemd

Day 6

Mix.install([
  {:kino, "~> 0.11.3"}
])

Part 1

input = Kino.Input.textarea("Please enter the input here:")
defmodule Day6Part1 do
  def solve(input) do
    [time, distance] = String.split(input, "\n", trim: true)

    ["Time", time] = String.split(time, ":", trim: true)
    time = String.split(time, " ", trim: true) |> Enum.map(&String.to_integer/1)

    ["Distance", distance] = String.split(distance, ":", trim: true)
    distance = String.split(distance, " ", trim: true) |> Enum.map(&String.to_integer/1)

    Enum.zip(time, distance)
    |> Enum.map(fn {t, d} ->
      0..t
      |> Enum.filter(&(&1 * (t - &1) > d))
      |> length()
    end)
    |> Enum.product()
  end
end
{:module, Day6Part1, <<70, 79, 82, 49, 0, 0, 10, ...>>, {:solve, 1}}
input
|> Kino.Input.read()
|> Day6Part1.solve()
1710720

Part 2

defmodule Day6Part2 do
  def solve(input) do
    [time, distance] = String.split(input, "\n", trim: true)

    ["Time", time] = String.split(time, ":", trim: true)

    time =
      String.split(time, " ", trim: true)
      |> Enum.reduce("", fn x, acc -> acc <> x end)
      |> String.to_integer()

    ["Distance", distance] = String.split(distance, ":", trim: true)

    distance =
      String.split(distance, " ", trim: true)
      |> Enum.reduce("", fn x, acc -> acc <> x end)
      |> String.to_integer()

    # x(a-x) is a parabola and it's reflected along it's mid point
    # we can do a binary search on the first half (it's increasing) and double the result
    first_value = search(0, div(time, 2), time, distance, -1)
    time - 2 * first_value + 1
  end

  defp search(left, right, _, _, guess) when right < left, do: guess

  defp search(left, right, t, d, guess) do
    mid = div(left + right, 2)
    value = mid * (t - mid)

    cond do
      value <= d -> search(mid + 1, right, t, d, guess)
      true -> search(left, mid - 1, t, d, mid)
    end
  end
end
{:module, Day6Part2, <<70, 79, 82, 49, 0, 0, 12, ...>>, {:search, 5}}
input
|> Kino.Input.read()
|> Day6Part2.solve()
35349468