Day 07
Mix.install([:kino_aoc])
Kino.configure(inspect: [charlists: :as_lists])
Input
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2024", "7", System.fetch_env!("LB_ADVENT_OF_CODE_SESSION"))
parsed =
puzzle_input
|> String.split("\n")
|> Enum.map(fn x ->
[total, nums] = String.split(x, ":")
nums = String.split(nums, " ", trim: true) |> Enum.map(&String.to_integer/1)
{String.to_integer(total), nums}
end)
Part 1
defmodule Part1 do
def create_op_combos(len) do
Enum.reduce(1..(len - 1), [[]], fn _, acc ->
for combination <- acc, operator <- ["+", "*"] do
combination ++ [operator]
end
end)
end
end
Enum.filter(parsed, fn {total, [head | tail] = ints} ->
combos = ints
|> length()
|> Part1.create_op_combos()
Enum.any?(combos, fn combo ->
total === elem(Enum.reduce(tail, {head, combo}, fn num, {total, [op | rest]} ->
case op do
"+" -> {total + num, rest}
"*" -> {total * num, rest}
end
end), 0)
end)
end)
|> Enum.map(&elem(&1, 0))
|> Enum.sum()
Part 2
defmodule Part2 do
def create_op_combos(len) do
Enum.reduce(1..(len - 1), [[]], fn _, acc ->
for combination <- acc, operator <- ["+", "*", "||"] do
combination ++ [operator]
end
end)
end
end
Task.async_stream(parsed, fn {total, [head | tail] = ints} ->
combos = ints
|> length()
|> Part2.create_op_combos()
if Enum.any?(combos, fn combo ->
total === elem(Enum.reduce(tail, {head, combo}, fn num, {total, [op | rest]} ->
case op do
"+" -> {total + num, rest}
"*" -> {total * num, rest}
"||" -> {String.to_integer("#{total}#{num}"), rest}
end
end), 0)
end), do: total, else: 0
end, ordered: false, timeout: :infinity)
|> Enum.map(&elem(&1, 1))
|> Enum.sum()