AOC 2022-03 (Rucksack Reorganization)

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

Common Code

defmodule Priority do
  @values "abcdefghijklmnopqrstuvwzyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
          |> String.graphemes()
          |> Enum.with_index()
          |> Map.new()

  def of(char), do: Map.get(@values, char) + 1

  def from_mapset(ms) do
    list = MapSet.to_list(ms)

    case Enum.count(list) do
      1 -> list |> hd() |> of()
      _ -> raise "Invalid MapSet. count > 1"
    end
  end
end

Input

input = Kino.Input.textarea("Input")
rucksacks =
  input
  |> Kino.Input.read()
  |> String.split()

Part 1

Determine the total priority of items appearing in both halves of each rucksack

Enum.map(rucksacks, fn sack ->
  sack = String.graphemes(sack)

  Enum.chunk_every(sack, div(Enum.count(sack), 2))
  |> Enum.map(&MapSet.new/1)
end)
|> Enum.map(fn [section1, section2] ->
  MapSet.intersection(section1, section2)
  |> Priority.from_mapset()
end)
|> Enum.sum()

Part 2

Scan each set of 3 rucksacks for the item they have in common and sum the priorities for those items.

Enum.map(rucksacks, fn sack ->
  sack
  |> String.graphemes()
  |> Enum.uniq()
  |> MapSet.new()
end)
|> Enum.chunk_every(3)
|> Enum.map(fn [sack1, sack2, sack3] ->
  sack1
  |> MapSet.intersection(sack2)
  |> MapSet.intersection(sack3)
  |> Priority.from_mapset()
end)
|> Enum.sum()