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

No Space Left On Device

livebook/day07.livemd

No Space Left On Device

Mix.install([{:kino, "~> 0.7.0"}])

Input

input = Kino.Input.textarea("Input:")
input = Kino.Input.read(input) |> String.trim() |> String.split("\n")
defmodule M do
  def walk(input) do
    {_, sizes} =
      Enum.reduce(input, {["/"], %{}}, fn
        _line = "$ cd /", _acc = {_pwd, sizes} ->
          {["/"], sizes}

        _line = "$ cd ..", _acc = {_pwd = [_ | up], sizes} ->
          {up, sizes}

        _line = "$ cd " <> rel, _acc = {pwd, sizes} ->
          {[rel | pwd], sizes}

        _line = "$ ls", acc ->
          acc

        _line = "dir " <> _, acc ->
          acc

        _line = file, _acc = {pwd, sizes} ->
          [size, _name] = String.split(file, " ")
          size = String.to_integer(size)

          sizes = account(pwd, size, sizes)
          {pwd, sizes}
      end)

    sizes
  end

  defp account(dir = [_ | parent], size, sizes) do
    sizes = Map.update(sizes, dir, size, fn s -> s + size end)
    account(parent, size, sizes)
  end

  defp account([], _size, sizes) do
    sizes
  end
end

sizes = M.walk(input)
sizes
|> Enum.filter(fn {_, size} -> size <= 100_000 end)
|> Enum.map(fn {_, size} -> size end)
|> Enum.sum()
used = Map.get(sizes, ["/"])
total = 70_000_000
required = 30_000_000
free = total - used
to_free = required - free
# Find the smallest directory that is larger than 'to_free':
Enum.map(sizes, fn {_dir, size} -> size end)
|> Enum.sort(:asc)
|> Enum.find(fn size -> size >= to_free end)