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

Day 3

2022/day_3.livemd

Day 3

Mix.install(
  [
    {:advent_of_code_utils, "~> 3.1"}
  ],
  config: [
    advent_of_code_utils: [session: System.fetch_env!("LB_AOC_TOKEN")]
  ]
)

Mix.Tasks.Aoc.Get.run(["--year", "2022", "--day", "3"])

Inputs

example_input = AOC.example_string(2022, 3)
input = AOC.input_string(2022, 3)

Parser

defmodule Parser do
  def parse_line(line) do
    String.split_at(line, div(String.length(line), 2))
  end

  def parse_part_1(input) do
    input
    |> String.trim()
    |> String.split("\n")
    |> Enum.map(&parse_line/1)
  end

  def parse_part_2(input) do
    input
    |> String.trim()
    |> String.split("\n")
  end
end

Utils

defmodule Utils do
  def tuple_map(list_of_tuples, fun) do
    list_of_tuples
    |> Enum.map(fn tuple ->
      tuple
      |> Tuple.to_list()
      |> Enum.map(fun)
      |> List.to_tuple()
    end)
  end
end

Rucksack

defmodule Rucksack do
  # a-z
  def priority(item) when is_integer(item) and 97 <= item and item <= 122 do
    item - 96
  end

  # A-Z
  def priority(item) when is_integer(item) and 65 <= item and item <= 90 do
    item - 38
  end

  def priority(item) when is_binary(item) and byte_size(item) == 1 do
    item
    |> :binary.first()
    |> priority
  end
end

Part 1

example_input
|> Parser.parse_part_1()
|> Utils.tuple_map(fn compartment_contents ->
  compartment_contents
  |> String.split("", trim: true)
  |> MapSet.new()
end)
|> Enum.map(fn {compartment_one, compartment_two} ->
  MapSet.intersection(compartment_one, compartment_two)
end)
|> Enum.map(&amp;MapSet.to_list/1)
|> Enum.map(&amp;hd/1)
|> Enum.map(&amp;Rucksack.priority/1)
|> Enum.sum()
input
|> Parser.parse_part_1()
|> Utils.tuple_map(fn compartment_contents ->
  compartment_contents
  |> String.split("", trim: true)
  |> MapSet.new()
end)
|> Enum.map(fn {compartment_one, compartment_two} ->
  MapSet.intersection(compartment_one, compartment_two)
end)
|> Enum.map(&amp;MapSet.to_list/1)
|> Enum.map(&amp;hd/1)
|> Enum.map(&amp;Rucksack.priority/1)
|> Enum.sum()

Part 2

example_input
|> Parser.parse_part_2()
|> Enum.chunk_every(3)
|> Enum.map(&amp;List.to_tuple/1)
|> Utils.tuple_map(fn compartment_contents ->
  compartment_contents
  |> String.split("", trim: true)
  |> MapSet.new()
end)
|> Enum.map(fn {elf_one, elf_two, elf_three} ->
  elf_one
  |> MapSet.intersection(elf_two)
  |> MapSet.intersection(elf_three)
end)
|> Enum.map(&amp;MapSet.to_list/1)
|> Enum.map(&amp;hd/1)
|> Enum.map(&amp;Rucksack.priority/1)
|> Enum.sum()
input
|> Parser.parse_part_2()
|> Enum.chunk_every(3)
|> Enum.map(&amp;List.to_tuple/1)
|> Utils.tuple_map(fn compartment_contents ->
  compartment_contents
  |> String.split("", trim: true)
  |> MapSet.new()
end)
|> Enum.map(fn {elf_one, elf_two, elf_three} ->
  elf_one
  |> MapSet.intersection(elf_two)
  |> MapSet.intersection(elf_three)
end)
|> Enum.map(&amp;MapSet.to_list/1)
|> Enum.map(&amp;hd/1)
|> Enum.map(&amp;Rucksack.priority/1)
|> Enum.sum()