AOC 2022 - Day 03
Mix.install([
{:kino_aoc, "~> 0.1"}
])
AOC Helper
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2022", "3", System.fetch_env!("LB_AOC_SESSION"))
Part 1
Code
defmodule PartOne do
def find_shared_item({compartment1, compartment2}) do
MapSet.intersection(
MapSet.new(compartment1),
MapSet.new(compartment2)
)
|> MapSet.to_list()
|> List.first()
end
# convert character to ascii code
def priority(item) when is_bitstring(item), do: :binary.first(item) |> priority()
# ascii code for 'A' is 65 and 'Z' is 90. The offset for the puzzles values is 38
def priority(item) when item >= 65 and item <= 90, do: item - 38
# ascii code for 'a' is 97 and 'z' is 122. The offset for the puzzles values is 96
def priority(item) when item >= 97 and item <= 122, do: item - 96
def solve(input) do
IO.puts("--- Part One ---")
IO.puts("Result: #{run(input)}")
end
def run(input) do
input
|> String.split("\n")
|> Enum.reduce(0, fn rucksack, total ->
contents = rucksack |> String.trim() |> String.graphemes()
midpoint = contents |> length() |> Kernel./(2) |> round()
contents
|> Enum.split(midpoint)
|> find_shared_item()
|> priority()
|> Kernel.+(total)
end)
end
end
Test
ExUnit.start(autorun: false)
defmodule PartOneTest do
use ExUnit.Case, async: true
import PartOne
@input "vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw"
@expected 157
test "part one" do
actual = run(@input)
assert actual == @expected
end
end
ExUnit.run()
Solution
PartOne.solve(puzzle_input)
Part 2
Code
defmodule PartTwo do
def find_badge([rucksack1, rucksack2, rucksack3]) do
rucksack1
|> MapSet.new()
|> MapSet.intersection(MapSet.new(rucksack2))
|> MapSet.intersection(MapSet.new(rucksack3))
|> MapSet.to_list()
|> List.first()
end
# convert character to ascii code
def priority(item) when is_bitstring(item), do: :binary.first(item) |> priority()
# ascii code for 'A' is 65 and 'Z' is 90. The offset for the puzzles values is 38
def priority(item) when item >= 65 and item <= 90, do: item - 38
# ascii code for 'a' is 97 and 'z' is 122. The offset for the puzzles values is 96
def priority(item) when item >= 97 and item <= 122, do: item - 96
def solve(input) do
IO.puts("--- Part Two ---")
IO.puts("Result: #{run(input)}")
end
def run(input) do
input
|> String.split("\n")
|> Enum.chunk_every(3)
|> Enum.map(fn group ->
Enum.map(group, &(&1 |> String.trim() |> String.graphemes()))
end)
|> Enum.reduce(0, fn rucksacks, total ->
rucksacks
|> find_badge()
|> priority()
|> Kernel.+(total)
end)
end
end
Test
ExUnit.start(autorun: false)
defmodule PartTwoTest do
use ExUnit.Case, async: true
import PartTwo
@input "vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw"
@expected 70
test "part two" do
actual = run(@input)
assert actual == @expected
end
end
ExUnit.run()
Solution
PartTwo.solve(puzzle_input)