aoc/22/lib/days/day7.ex

83 lines
1.7 KiB
Elixir
Raw Normal View History

2023-04-17 18:18:20 +00:00
defmodule AOC.Day7 do
use AOC.Day, day: 7
def parse_input(lines) do
Enum.map(lines, fn
"$ cd " <> arg ->
{:cd, arg}
"$ ls" ->
:ls
"dir " <> arg ->
{:dir, arg}
line ->
[size, file] = String.split(line)
{:file, String.to_integer(size), file}
end)
end
def part1(input) do
input
|> get_file_sizes()
|> get_directory_sizes()
|> Enum.map(fn {_, size} -> size end)
|> Enum.filter(&(&1 <= 100_000))
|> Enum.sum()
end
def part2(input) do
file_sizes = get_file_sizes(input)
total_size =
file_sizes
|> Enum.map(&elem(&1, 1))
|> Enum.sum()
size_needed = total_size - 40_000_000
file_sizes
|> get_directory_sizes()
|> Enum.map(&elem(&1, 1))
|> Enum.filter(fn size -> size >= size_needed end)
|> Enum.min()
end
def get_file_sizes(input) do
Enum.reduce(input, {[], []}, fn
{:cd, "/"}, {_, sizes} ->
{["/"], sizes}
{:cd, ".."}, {[_ | path], sizes} ->
{path, sizes}
{:cd, dir}, {path, sizes} ->
{[dir | path], sizes}
{:file, size, file}, {path, sizes} ->
{path, [{[file | path], size} | sizes]}
_, acc ->
acc
end)
|> elem(1)
end
def get_directory_sizes(file_sizes) do
file_sizes
|> Enum.reduce(%{}, fn {[_ | path], size}, acc ->
path = Enum.reverse(path)
update_directory_size(acc, size, path)
end)
end
def update_directory_size(sizes, file_size, file_path) do
Enum.reduce(file_path, {sizes, []}, fn dir, {sizes, cur_path} ->
cur_path = [dir | cur_path]
{Map.update(sizes, cur_path, file_size, &(&1 + file_size)), cur_path}
end)
|> elem(0)
end
end