Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Advent of Code 2022 - Day 7

day07.livemd

Advent of Code 2022 - Day 7

Day 7: No Space Left On Device

Description

Utils

defmodule Load do
  def file(path) do
    File.read!(__DIR__ <> path)
    |> String.split("\n")
  end

  def string(value) do
    value |> String.split("\n", trim: true)
  end
end

Input

input = Load.file("/data/day07.txt")

Part 1

Find all of the directories with a total size of at most 100000. What is the sum of the total sizes of those directories?

defmodule Part1 do
  def count_dir_size(input) do
    count_dir_size(input, %{"/" => 0}, ["/"])
  end

  defp count_dir_size([], sizes, _active_dirs) do
    sizes
  end

  defp count_dir_size([line | input], sizes, active_dirs) do
    [command | args] = line |> String.split()

    case command do
      "$" ->
        [program | arg] = args

        case program do
          "cd" ->
            [dir] = arg

            case dir do
              "/" ->
                count_dir_size(input, sizes, ["/"])

              ".." ->
                count_dir_size(input, sizes, active_dirs |> tl())

              dir ->
                full_dir = full_dir(hd(active_dirs), dir)
                count_dir_size(input, sizes, [full_dir | active_dirs])
            end

          _ ->
            count_dir_size(input, sizes, active_dirs)
        end

      "dir" ->
        [dir_name] = args

        count_dir_size(
          input,
          sizes |> Map.put(full_dir(hd(active_dirs), dir_name), 0),
          active_dirs
        )

      filesize_string ->
        filesize = filesize_string |> String.to_integer()

        sizes =
          active_dirs
          |> Enum.reduce(sizes, fn dir_name, sizes ->
            %{sizes | dir_name => sizes[dir_name] + filesize}
          end)

        count_dir_size(input, sizes, active_dirs)
    end
  end

  defp full_dir(active_dir, dir) do
    "#{active_dir}/#{dir}" |> String.trim_leading("/")
  end
end

input
|> Part1.count_dir_size()
|> Enum.reduce(0, fn {_dir_name, value}, result ->
  if value <= 100_000 do
    result + value
  else
    result
  end
end)

Result

1206825

Part 2

Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. What is the total size of that directory?

sizes =
  input
  |> Part1.count_dir_size()

total_size = sizes["/"]

unused = 70_000_000 - total_size
enough = 30_000_000 - unused

sizes
|> Enum.filter(fn {_name, size} -> size > enough end)
|> Enum.map(fn {_name, size} -> size end)
|> Enum.min()

Result

9608311