input = Kino.Input.textarea("Puzzle Input")
defmodule RuckSack do
def priorities(input) do
input
|> process_input()
|> Enum.map(
&(&1
|> compartments()
|> get_diff()
|> priority())
)
|> Enum.sum()
end
def badges(input) do
input
|> process_input()
|> Enum.chunk_every(3)
|> Enum.map(
&(&1
|> get_badge()
|> priority())
)
|> Enum.sum()
end
defp compartments(list) do
Enum.split(
list,
list
|> Enum.count()
|> Kernel.div(2)
)
end
defp get_diff({comp1, comp2}) do
MapSet.new(comp1)
|> MapSet.intersection(MapSet.new(comp2))
|> Enum.at(0)
end
defp get_badge([sack1, sack2, sack3]) do
MapSet.new(sack1)
|> MapSet.intersection(MapSet.new(sack2))
|> MapSet.intersection(MapSet.new(sack3))
|> Enum.at(0)
end
# A-Z in erlang is 65..90
# a-z in erlang is 97..122
defp priority(char) when char in 65..90, do: char - 38
defp priority(char) when char in 97..122, do: char - 96
defp process_input(input) do
input
|> String.split()
|> Enum.map(&String.to_charlist/1)
end
end
part_1 =
input
|> Kino.Input.read()
|> RuckSack.priorities()
part_2 =
input
|> Kino.Input.read()
|> RuckSack.badges()
{part_1, part_2}
ExUnit.start(autorun: false)
defmodule RuckSackTest do
use ExUnit.Case, async: true
setup do
# paste your example data after line 8
input = ~s(
vJrwpWtwJgWrhcsFMMfFFhFp
jqHRNqRjqzjGDLGLrsFMfFZSrLrFZsSL
PmmdzqPrVvPwwTWBwg
wMqvLMZHhHMvwLHjbvcjnnSBnvTQFn
ttgJtRGJQctTZtZT
CrZsJsPPZsGzwwsLwLmpwMDw
)
{:ok, input: input}
end
test "priorities", %{input: input} do
assert RuckSack.priorities(input) == 157
end
test "badges", %{input: input} do
assert RuckSack.badges(input) == 70
end
end
ExUnit.run()