Day 7: No Space Left On Device
Mix.install([:kino])
input = Kino.Input.textarea("Please paste your input:")
Part 1
https://adventofcode.com/2022/day/7
data =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
struct_directory = fn
[command | rest_commands], directory, r_current_path, fun ->
case command do
"$ cd /" ->
fun.(rest_commands, directory, [], fun)
"$ cd .." ->
fun.(rest_commands, directory, tl(r_current_path), fun)
"$ cd " <> directory_name ->
fun.(rest_commands, directory, [directory_name | r_current_path], fun)
"$ ls" ->
{ls_results, rest_commands} =
rest_commands
|> Enum.split_while(&(not String.starts_with?(&1, "$")))
new_directory =
ls_results
|> Enum.reduce(directory, fn
"dir " <> directory_name, directory ->
directory
|> put_in(Enum.reverse([directory_name | r_current_path]), %{})
file, directory ->
[size_str, filename] = String.split(file, " ")
size = size_str |> String.to_integer()
directory
|> put_in(Enum.reverse([filename | r_current_path]), size)
end)
fun.(rest_commands, new_directory, r_current_path, fun)
end
[], directory, _r_current_path, _fun ->
directory
end
directory = struct_directory.(data, %{}, [], struct_directory)
find_small_directory_sizes = fn
%{} = directory, result, fun ->
{total_size, result} =
directory
|> Enum.reduce({0, result}, fn {_name, value}, {total_size, result} ->
{sub_total_size, result} = fun.(value, result, fun)
{total_size + sub_total_size, result}
end)
case total_size < 100_000 do
true -> {total_size, total_size + result}
false -> {total_size, result}
end
size, result, _fun ->
{size, result}
end
{total_size, result} = find_small_directory_sizes.(directory, 0, find_small_directory_sizes)
_answer1 = result
Part 2
https://adventofcode.com/2022/day/7#part2
total_disk_space = 70_000_000
needed_unused_space = 30_000_000
unused_space = total_disk_space - total_size
needed_to_be_deleted_space = needed_unused_space - unused_space
list_candidate_directories = fn
%{} = directory, candidates, fun ->
{total_size, candidates} =
directory
|> Enum.reduce({0, candidates}, fn {_name, value}, {total_size, candidates} ->
{sub_total_size, candidates} = fun.(value, candidates, fun)
{total_size + sub_total_size, candidates}
end)
case total_size >= needed_to_be_deleted_space do
true -> {total_size, [total_size | candidates]}
false -> {total_size, candidates}
end
size, result, _fun ->
{size, result}
end
{_, candidates} = list_candidate_directories.(directories, [], list_candidate_directories)
_answer2 =
candidates
|> Enum.min()