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

Advent of code day 07

2024/livebooks/day-07.livemd

Advent of code day 07

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

Setup input

example = Kino.Input.textarea("Please paste your input example:")
input = Kino.Input.textarea("Please paste your real input:")

Part 01

defmodule Solver do
  def possible?(target, nums) do
    possible?(target, nums, 0)
  end

  defp possible?(t, [], sum), do: t == sum

  defp possible?(t, [n | nums], sum) do
    possible?(t, nums, n + sum) || possible?(t, nums, n * sum)
  end
end
input =
  example
  |> Kino.Input.read()
  |> String.split(["\n", ": "], trim: true)
  |> Enum.chunk_every(2)
  |> Enum.reduce(%{}, fn [target, rest], acc ->
    Map.put(
      acc,
      String.to_integer(target),
      String.split(rest) |> Enum.map(&String.to_integer(&1))
    )
  end)

:timer.tc(fn ->
  Enum.reduce(input, 0, fn {k, v}, acc ->
    case Solver.possible?(k, v) do
      true -> acc + k
      false -> acc
    end
  end)
end)
|> then(fn {time, value} ->
  "it took #{div(time, 1000)} ms and result is #{value}"
end)

Part 02

defmodule Solver2 do
  def possible?(target, nums) do
    possible?(target, nums, 0)
  end

  defp possible?(t, [], sum), do: t == sum

  defp possible?(t, [n | nums], sum) do
    possible?(t, nums, n + sum) ||
      possible?(t, nums, n * sum) ||
      possible?(t, nums, sum * 10 ** digits(n) + n)
  end

  defp digits(n) do
    Integer.to_string(n) |> String.length()
  end
end
:timer.tc(fn ->
  Task.async_stream(input, fn {k, v} ->
    case Solver2.possible?(k, v) do
      true -> k
      false -> 0
    end
  end)
  |> Enum.reduce(0, fn {:ok, n}, acc -> n + acc end)
end)
|> then(fn {time, value} ->
  "it took #{div(time, 1000)} ms and result is #{value}"
end)