Advent of Code 2024/7
Mix.install([
{:kino, "~> 0.14.2"}
])
Section
input = Kino.Input.textarea("input")
defmodule AoC2024_7 do
def parse(input) do
Kino.Input.read(input)
|> String.split("\n\n", trim: true)
|> Enum.map(fn part -> String.split(part, "\n", trim: true) |> Enum.map(fn row -> row_parser(row) end) end)
|> Enum.at(0)
end
def row_parser(row) do
[result, parts] = String.split(row, ":", trim: true)
{String.split(parts, " ", trim: true) |> Enum.map(fn part -> String.to_integer(part) end), String.to_integer(result)}
end
def step(list, operators \\ ["+", "*"])
def step([element | []], _operators), do: [[element]]
def step([element | rest], operators) do
step(rest, operators)
|> Enum.flat_map(fn path -> Enum.map(operators, fn operator -> [element, operator] ++ path end) end)
end
def split_by_cocatenation(list) do
list
|> Enum.chunk_by(fn x -> x == "||" end)
|> Enum.reject(fn x -> x == ["||"] end)
end
def calculate_position(item, acc, "+"), do: acc + item
def calculate_position(item, acc, "*"), do: acc * item
def calculate_position(item, acc, "||"), do: String.to_integer(Enum.join([acc, item]))
def calculate(list) do
tl(list)
|> Enum.chunk_every(2)
|> Enum.reduce(hd(list), fn [op, item], acc -> calculate_position(item, acc, op) end)
end
def check_row({parts, result}, operators \\ ["+", "*"]) do
Enum.any?(step(parts, operators), fn el -> calculate(el) == result end)
end
def part_1(input) do
input
|> parse
|> Enum.filter(fn row -> check_row(row) end)
|> Enum.map(fn row -> elem(row, 1) end)
|> Enum.sum
end
def part_2(input) do
input
|> parse
|> Enum.filter(fn row -> check_row(row, ["+", "*", "||"]) end)
|> Enum.map(fn row -> elem(row, 1) end)
|> Enum.sum
end
end
AoC2024_7.part_1(input)
AoC2024_7.part_2(input)