# Advent of Code 2022 - Day 3
```elixir
Mix.install([
{:req_aoc, github: "mcrumm/req_aoc", ref: "28e3813"}
])
```
## Puzzle description
[Day 3: Rucksack Reorganization](https://adventofcode.com/2022/day/3).
<!-- livebook:{"break_markdown":true} -->
Note: I grew tired of downloading my user input, so I figured out how to download the input from the Advent of Code site. You need to [get your session cookie](https://github.com/mcrumm/req_aoc#how-to-get-the-session-cookie) on adventofcode.com. Use DevTools or similar and inspect the Request Headers to find your session id and then add it to Livebook secrets as `AOC_SESSION`.
## Input
```elixir
defmodule Input do
def load! do
ReqAOC.fetch!({2022, 03, System.fetch_env!("LB_AOC_SESSION")}, max_retries: 0)
end
@doc """
Splits a string by newlines.
"""
def to_lines(input) when is_binary(input) do
input
|> String.trim("\n")
|> String.split("\n")
end
end
```
## Solution
```elixir
defmodule Part1 do
# preflight:
## split string into lines (without break characters)
def run(input) do
input
|> Enum.map(fn line ->
# split the rucksack into two equal compartments
{head, tail} = String.split_at(line, div(String.length(line), 2))
head
|> String.codepoints()
|> Enum.reduce_while(:ok, fn code, _ ->
case :binary.match(tail, code) do
{_, 1} -> {:halt, code |> priority()}
:nomatch -> {:cont, :ok}
end
end)
end)
|> Enum.sum()
end
lower = Enum.into(?a..?z, [])
upper = Enum.into(?A..?Z, [])
alphabet = lower ++ upper
def priority(x) when is_binary(x) do
x |> :binary.first() |> priority()
end
for {c, k} <- Enum.with_index(alphabet, 1) do
def priority(unquote(c)), do: unquote(k)
end
end
defmodule Part2 do
# preflight:
## split string into lines (without break characters)
def run(input) do
# chunk lines into groups of three
# find codepoint intersecting all three lines
# convert to char value
# sum
input
|> Enum.chunk_every(3)
|> Enum.map(fn [a, b, c] ->
# convert a to codepoints
# look for match in b
a
|> String.codepoints()
|> Enum.reduce_while(nil, fn code, acc ->
# find match in b
case :binary.match(b, code) do
{_, _} ->
# find match in c
case :binary.match(c, code) do
{_, _} ->
# success! return the priority value
{:halt, Part1.priority(code)}
:nomatch ->
# continue to next character
{:cont, acc}
end
:nomatch ->
# continue to next character
{:cont, acc}
end
end)
end)
|> Enum.sum()
end
end
ExUnit.start(autorun: false)
defmodule Test do
use ExUnit.Case, async: true
@example_input ~s(
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
)
@input Input.load!()
test "priority" do
for {l, k} <- Enum.with_index(?a..?z, 1) do
assert Part1.priority(l) == k
end
for {u, k} <- Enum.with_index(?A..?Z, 27) do
assert Part1.priority(u) == k
end
end
test "part 1" do
assert @example_input |> Input.to_lines() |> Part1.run() === 157
@input |> Input.to_lines() |> Part1.run() |> dbg()
end
test "part 2" do
assert @example_input |> Input.to_lines() |> Part2.run() === 70
@input |> Input.to_lines() |> Part2.run() |> dbg()
end
end
ExUnit.configure(trace: true)
ExUnit.run()
```