AoC 2022 Day 7
Mix.install([:kino])
defmodule Utils do
def split(line, sep \\ "") do
String.split(line, sep, trim: true)
end
def split_all_lines(text, sep \\ "") do
text
|> String.split("\n", trim: true)
|> Enum.map(&split(&1, sep))
end
def to_numbers(number) when is_binary(number) do
String.to_integer(number)
end
def to_numbers(numbers) when is_list(numbers) do
Enum.map(numbers, &to_numbers/1)
end
def to_matrix(text, sep \\ "") do
text
|> split_all_lines(sep)
|> then(fn data ->
for {row, r} <- Enum.with_index(data), {col, c} <- Enum.with_index(row) do
{{r, c}, col}
end
end)
|> Map.new()
end
end
Setup
import Utils
input = Kino.Input.textarea("Input:")
text = Kino.Input.read(input)
data = split(text, "\n")
defmodule P do
def cd(_p, "/") do
"/"
end
def cd(p, "..") do
Path.dirname(p)
end
def cd(p, other) do
Path.join(p, other)
end
end
{_, data} =
Enum.reduce(data, {"", %{}}, fn
"$ cd " <> path, {curr, data} ->
{P.cd(curr, path), data}
"$ ls", acc ->
acc
"dir " <> _dir, acc ->
acc
file, {curr, data} ->
[size, name] = String.split(file, " ")
{curr, Map.put(data, Path.join(curr, name), String.to_integer(size))}
end)
P1
sizes =
data
|> Enum.reduce(%{}, fn {path, size}, sizes ->
Stream.iterate(path |> Path.split() |> Enum.reverse() |> Enum.drop(1), &tl/1)
|> Enum.take_while(fn p -> p != [] end)
|> Enum.reduce(sizes, fn parts, sizes ->
Map.update(sizes, Path.join(Enum.reverse(parts)), size, &(&1 + size))
end)
end)
sizes
|> Enum.filter(fn {_, v} -> v < 100_000 end)
|> Enum.map(fn {_k, v} -> v end)
|> Enum.sum()
P2
total = sizes["/"]
Enum.filter(sizes, fn {_p, v} -> total - v < 40_000_000 end)
|> Enum.map(fn {_k, v} -> v end)
|> Enum.min()