Day 7
Mix.install([
{:kino, "~> 0.14.2"}
])
Part 1
calibrations = Kino.FS.file_path("day7-in.txt")
|> File.read!()
|> String.trim()
|> String.split("\n")
|> Enum.map(fn line ->
{cal, nums} = String.split(line, ":", trim: true)
|> List.to_tuple()
cal = String.to_integer(cal)
nums = String.trim(nums) |> String.split() |> Enum.map(&String.to_integer/1)
{cal, nums}
end)
defmodule Mathinator do
def num_if_matched({expected_result, values}) do
if expected_result in try_ops(values), do: expected_result, else: 0
end
defp try_ops([only]), do: [only]
defp try_ops([first | rest]) do
try_ops(rest) |> Enum.flat_map(& [first + &1, first * &1])
end
end
start = System.monotonic_time(:microsecond)
result = calibrations
|> Stream.map(fn {result, values} -> {result, Enum.reverse(values)} end)
|> Stream.map(&Mathinator.num_if_matched/1)
|> Enum.sum()
IO.puts("Result: #{result}")
elapsed = System.monotonic_time(:microsecond) - start
IO.puts "Finished in #{elapsed / 1000}ms"
Part 2
defmodule Mathinator2 do
def num_if_matched({expected_result, values}) do
if expected_result in try_ops(values), do: expected_result, else: 0
end
defp concat(a, b) do
:math.pow(10, (1 + floor(:math.log10(b)))) * a + b |> round()
end
defp try_ops([only]), do: [only]
defp try_ops([first | rest]) do
try_ops(rest) |> Stream.flat_map(& [&1 + first, &1 * first, concat(&1, first)])
end
end
start = System.monotonic_time(:microsecond)
result = calibrations
|> Stream.map(fn {result, values} -> {result, Enum.reverse(values)} end)
|> Task.async_stream(&Mathinator2.num_if_matched/1)
|> Enum.reduce(0, fn {:ok, num}, acc -> num + acc end)
IO.puts("Result: #{result}")
elapsed = System.monotonic_time(:microsecond) - start
IO.puts "Finished in #{elapsed / 1000}ms"