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

Day Seven

day7.livemd

Day Seven

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

Section

input = Kino.Input.textarea("Input")
defmodule DaySeven do
  def solve1(input) do
    input
    |> String.split("\n", trim: true)
    |> parse()
    |> dir_sizes()
    |> Enum.filter(fn {_, s} -> s <= 100_000 end)
    |> Enum.map(fn {_, s} -> s end)
    |> Enum.sum()
  end

  def solve2(input) do
    dir_sizes =
      input
      |> String.split("\n", trim: true)
      |> parse()
      |> dir_sizes()

    used = dir_sizes[[]]
    free = 70_000_000 - used
    needed = 30_000_000 - free

    dir_sizes
    |> Enum.map(fn {_, s} -> s end)
    |> Enum.filter(fn s -> s >= needed end)
    |> Enum.sort()
    |> hd()
  end

  defp dir_sizes(%{files: files}) do
    Enum.reduce(files, %{}, fn {[_name | path], size}, acc ->
      update_dir_size(path, size, acc)
    end)
  end

  defp update_dir_size([], size, acc) do
    Map.update(acc, [], size, &amp;(&amp;1 + size))
  end

  defp update_dir_size(path, size, acc) do
    update_dir_size(Enum.drop(path, 1), size, Map.update(acc, path, size, &amp;(&amp;1 + size)))
  end

  defp parse(lines) do
    parse(lines, %{pwd: "/", files: %{}})
  end

  defp parse([], acc) do
    acc
  end

  defp parse(["$ cd /" | rest], acc) do
    parse(rest, %{acc | pwd: []})
  end

  defp parse(["$ cd .." | rest], acc) do
    parse(rest, %{acc | pwd: Enum.drop(acc.pwd, 1)})
  end

  defp parse(["$ cd " <> dir | rest], acc) do
    parse(rest, %{acc | pwd: [dir | acc.pwd]})
  end

  defp parse(["$ ls" | rest], acc) do
    {entries, rest} = Enum.split_while(rest, &amp;(!String.starts_with?(&amp;1, "$")))

    files =
      Enum.reduce(entries, acc.files, fn
        "dir" <> _, files ->
          files

        entry, files ->
          [size, name] = String.split(entry, " ")
          Map.put(files, [name | acc.pwd], String.to_integer(size))
      end)

    parse(rest, %{acc | files: files})
  end
end

DaySeven.solve2(Kino.Input.read(input))