aoc2022/day7.livemd
2022-12-12 21:16:05 +01:00

2.3 KiB

AOC 2022 - Day 7

Mix.install([
  {:req, "~> 0.3.3"}
])

Puzzle description

Day 7: No Space Left On Device.

Input

defmodule Load do
  def input do
    aoc_session = System.fetch_env!("LB_AOC_SESSION")
    input_url = "https://adventofcode.com/2022/day/7/input"
    Req.get!(input_url, headers: [cookie: "session=#{aoc_session}"]).body
  end
end

Solution

defmodule Util do
  def all_dir_sizes(input) do
    input
    |> String.split("\n", trim: true)
    |> Stream.reject(&(&1 == "$ ls" || match?("dir " <> _, &1)))
    |> Stream.concat(Stream.repeatedly(fn -> "$ cd .." end))
    |> Stream.transform(
      # initial accumulator
      [0],

      # reducer
      fn
        "$ cd ..", [_last] ->
          {:halt, nil}

        "$ cd ..", [leaving_size, parent_size | stack] ->
          {[leaving_size], [parent_size + leaving_size | stack]}

        "$ cd " <> _, stack ->
          {[], [0 | stack]}

        file, [size | stack] ->
          [filesize, _] = String.split(file, " ")
          {[], [size + String.to_integer(filesize) | stack]}
      end
    )
    |> Enum.to_list()
    |> Enum.reverse()
  end
end
defmodule Part1 do
  def run(input) do
    input
    |> Util.all_dir_sizes()
    |> Enum.reject(&(&1 > 100_000))
    |> Enum.sum()
  end
end

defmodule Part2 do
  def run(input) do
    dir_sizes = Util.all_dir_sizes(input)
    needed_space = 30_000_000 + hd(dir_sizes) - 70_000_000

    dir_sizes
    |> Enum.filter(&(&1 > needed_space))
    |> Enum.min()
  end
end

ExUnit.start(autorun: false)

defmodule Test do
  use ExUnit.Case, async: true
  @example_input ~s($ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k)
  @input Load.input()

  test "it loads the input" do
    assert String.length(@input) > 0
  end

  test "part 1 example" do
    assert Part1.run(@example_input) === 95437
  end

  test "part 1" do
    assert Part1.run(@input) === 919_137
  end

  test "part 2 example" do
    assert Part2.run(@example_input) === 24_933_642
  end

  test "part 2" do
    assert Part2.run(@input) === 2_877_389
  end
end

ExUnit.run()