137 lines
2.8 KiB
Text
137 lines
2.8 KiB
Text
|
# AOC 2022 - Day 3
|
||
|
|
||
|
```elixir
|
||
|
Mix.install([
|
||
|
{:req, "~> 0.3.3"}
|
||
|
])
|
||
|
```
|
||
|
|
||
|
## Puzzle description
|
||
|
|
||
|
[Day 3: Rucksack Reorganization](https://adventofcode.com/2022/day/3).
|
||
|
|
||
|
## Input
|
||
|
|
||
|
```elixir
|
||
|
defmodule Load do
|
||
|
def input do
|
||
|
aoc_session = System.fetch_env!("LB_AOC_SESSION")
|
||
|
input_url = "https://adventofcode.com/2022/day/3/input"
|
||
|
Req.get!(input_url, headers: [cookie: "session=#{aoc_session}"]).body
|
||
|
end
|
||
|
end
|
||
|
```
|
||
|
|
||
|
```elixir
|
||
|
defmodule A do
|
||
|
def intersection(str1, str2) do
|
||
|
str1_set = MapSet.new(String.graphemes(str1))
|
||
|
str2_set = MapSet.new(String.graphemes(str2))
|
||
|
MapSet.intersection(str1_set, str2_set)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
A.intersection("hello", "world")
|
||
|
```
|
||
|
|
||
|
## Solution
|
||
|
|
||
|
```elixir
|
||
|
defmodule Util do
|
||
|
@items String.split("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", "", trim: true)
|
||
|
|
||
|
def value_of(item) do
|
||
|
Enum.find_index(@items, fn c -> c == item end) + 1
|
||
|
end
|
||
|
|
||
|
def process(input) do
|
||
|
input
|
||
|
|> String.trim()
|
||
|
|> String.split("\n", trim: true)
|
||
|
end
|
||
|
|
||
|
def intersection(str1, str2) do
|
||
|
str1_set = MapSet.new(String.graphemes(str1))
|
||
|
str2_set = MapSet.new(String.graphemes(str2))
|
||
|
MapSet.intersection(str1_set, str2_set)
|
||
|
end
|
||
|
|
||
|
def intersection(str1, str2, str3) do
|
||
|
str1_set = MapSet.new(String.graphemes(str1))
|
||
|
str2_set = MapSet.new(String.graphemes(str2))
|
||
|
str3_set = MapSet.new(String.graphemes(str3))
|
||
|
intersection = MapSet.intersection(str1_set, str2_set)
|
||
|
MapSet.intersection(intersection, str3_set)
|
||
|
end
|
||
|
end
|
||
|
```
|
||
|
|
||
|
```elixir
|
||
|
defmodule Part1 do
|
||
|
def run(input) do
|
||
|
input
|
||
|
|> Util.process()
|
||
|
|> Enum.map(&String.split_at(&1, div(String.length(&1), 2)))
|
||
|
|> Enum.reduce(0, fn {first, second}, acc ->
|
||
|
priority =
|
||
|
Util.intersection(first, second)
|
||
|
|> MapSet.to_list()
|
||
|
|> List.first()
|
||
|
|> Util.value_of()
|
||
|
|
||
|
acc + priority
|
||
|
end)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
defmodule Part2 do
|
||
|
def run(input) do
|
||
|
input
|
||
|
|> Util.process()
|
||
|
|> Enum.chunk_every(3)
|
||
|
|> Enum.map(fn [items1, items2, items3] ->
|
||
|
Util.intersection(items1, items2, items3)
|
||
|
|> MapSet.to_list()
|
||
|
|> List.first()
|
||
|
|> Util.value_of()
|
||
|
end)
|
||
|
|> Enum.reduce(&+/2)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
ExUnit.start(autorun: false)
|
||
|
|
||
|
defmodule Test do
|
||
|
use ExUnit.Case, async: true
|
||
|
@example_input ~s(vJrwpWtwJgWrhcsFMMfFFhFp
|
||
|
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
|
||
|
PmmdzqPrVvPwwTWBwg
|
||
|
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
|
||
|
ttgJtRGJQctTZtZT
|
||
|
CrZsJsPPZsGzwwsLwLmpwMDw)
|
||
|
@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) === 157
|
||
|
end
|
||
|
|
||
|
test "part 1" do
|
||
|
assert Part1.run(@input) === 8105
|
||
|
end
|
||
|
|
||
|
test "part 2 example" do
|
||
|
assert Part2.run(@example_input) === 70
|
||
|
end
|
||
|
|
||
|
test "part 2" do
|
||
|
assert Part2.run(@input) === 0
|
||
|
end
|
||
|
end
|
||
|
|
||
|
ExUnit.run()
|
||
|
```
|