Advent of Code 2022
Mix.install([
{:req, "~> 0.3.2"}
])
Set up
aoc_session = System.fetch_env!("LB_AOC_SESSION")
get_input = fn url ->
Req.get!(url, headers: [cookie: "session=#{aoc_session}"]).body
|> String.split("\n")
end
Day 1: Part 1
day_one_input_url = "https://adventofcode.com/2022/day/1/input"
day_one_input = get_input.(day_one_input_url)
day_one_input
|> Enum.chunk_by(fn pack -> pack == "" end)
|> Enum.filter(fn pack -> pack != [""] end)
|> Enum.map(fn pack -> Enum.map(pack, &String.to_integer/1) end)
|> Enum.map(fn pack -> Enum.sum(pack) end)
|> Enum.max()
Day 1: Part 2
day_one_input
|> Enum.chunk_by(fn pack -> pack == "" end)
|> Enum.filter(fn pack -> pack != [""] end)
|> Enum.map(fn pack -> Enum.map(pack, &String.to_integer/1) end)
|> Enum.map(fn pack -> Enum.sum(pack) end)
|> Enum.sort(:desc)
|> Enum.take(3)
|> Enum.sum()
Day 2: Part 1
day_two_input_url = "https://adventofcode.com/2022/day/2/input"
day_two_input = get_input.(day_two_input_url)
defmodule Day2Scorer1 do
def to_play({_, _} = t),
do:
t
|> Tuple.to_list()
|> Enum.map(&to_play/1)
|> List.to_tuple()
def to_play(play) do
case play do
:A -> :Rock
:B -> :Paper
:C -> :Scissors
:X -> :Rock
:Y -> :Paper
:Z -> :Scissors
end
end
def outcome(game) do
case game do
{:Rock, :Scissors} -> :loss
{:Scissors, :Paper} -> :loss
{:Paper, :Rock} -> :loss
{:Scissors, :Rock} -> :win
{:Rock, :Paper} -> :win
{:Paper, :Scissors} -> :win
{left, right} when left == right -> :tie
end
end
def outcome_points(outcome) do
case outcome do
:loss -> 0
:tie -> 3
:win -> 6
end
end
def play_points(play) do
case play do
:Rock -> 1
:Paper -> 2
:Scissors -> 3
end
end
def determine_points(game) do
play = to_play(game)
{_, your_play} = play
outcome = outcome(play)
outcome_points(outcome) + play_points(your_play)
end
end
day_two_input
|> Enum.map(fn strat -> String.trim(strat) end)
|> Enum.map(fn strat -> String.split(strat, " ") end)
|> Enum.map(fn strat -> Enum.map(strat, &String.to_atom/1) end)
|> Enum.map(&List.to_tuple/1)
|> Enum.filter(fn
{:""} -> false
_ -> true
end)
|> Enum.map(&Day2Scorer1.determine_points/1)
|> Enum.sum()
Day 2: Part 2
defmodule Day2Scorer2 do
def to_play(play) do
case play do
:A -> :Rock
:B -> :Paper
:C -> :Scissors
end
end
def wanted_outcome(yours) do
case yours do
:X -> :loss
:Y -> :tie
:Z -> :win
end
end
def select_move(outcome, theirs) do
case outcome do
:loss -> get_loss(theirs)
:tie -> get_tie(theirs)
:win -> get_win(theirs)
end
end
def get_win(theirs) do
case theirs do
:Rock -> :Paper
:Scissors -> :Rock
:Paper -> :Scissors
end
end
def get_tie(theirs), do: theirs
def get_loss(theirs) do
case theirs do
:Rock -> :Scissors
:Scissors -> :Paper
:Paper -> :Rock
end
end
def outcome_points(outcome) do
case outcome do
:loss -> 0
:tie -> 3
:win -> 6
end
end
def play_points(play) do
case play do
:Rock -> 1
:Paper -> 2
:Scissors -> 3
end
end
def determine_points(game) do
{their_move, your_move} = game
their_play = to_play(their_move)
wanted_outcome = wanted_outcome(your_move)
your_play = select_move(wanted_outcome, their_play)
outcome_points = outcome_points(wanted_outcome)
play_points = play_points(your_play)
outcome_points + play_points
end
end
day_two_input
|> Enum.map(fn strat -> String.trim(strat) end)
|> Enum.map(fn strat -> String.split(strat, " ") end)
|> Enum.map(fn strat -> Enum.map(strat, &String.to_atom/1) end)
|> Enum.map(&List.to_tuple/1)
|> Enum.filter(fn
{:""} -> false
_ -> true
end)
|> Enum.map(&Day2Scorer2.determine_points/1)
|> Enum.sum()
Day 3: Part 1
day_three_input_url = "https://adventofcode.com/2022/day/3/input"
day_three_input = get_input.(day_three_input_url)
defmodule RuckSack do
@priority ~c("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
def priority(value) do
@priority |> Enum.find_index(fn a -> a == value end)
end
def split(rucksack) do
halflength = (String.length(rucksack) / 2) |> round
{String.slice(rucksack, 0, halflength), String.slice(rucksack, halflength, halflength)}
end
def compare({_, _} = pair) do
[a, b] =
pair
|> Tuple.to_list()
|> Enum.map(&String.graphemes/1)
|> Enum.map(&MapSet.new/1)
MapSet.intersection(a, b)
end
end
day_three_input
|> Enum.map(&RuckSack.split/1)
|> Enum.map(&RuckSack.compare/1)
|> Enum.map(&MapSet.to_list/1)
|> List.flatten()
|> List.to_charlist()
|> Enum.map(&RuckSack.priority/1)
|> Enum.sum()
Day 3: Part 2
defmodule RuckSack do
@priority ~c("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
def priority(value) do
@priority |> Enum.find_index(fn a -> a == value end)
end
def compare([_, _, _] = triple) do
[a, b, c] =
triple
|> Enum.map(&String.graphemes/1)
|> Enum.map(&MapSet.new/1)
MapSet.intersection(a, b) |> MapSet.intersection(c)
end
def compare(_), do: MapSet.new()
end
day_three_input
|> Enum.chunk_every(3)
|> Enum.map(&RuckSack.compare/1)
|> Enum.map(&MapSet.to_list/1)
|> List.flatten()
|> List.to_charlist()
|> Enum.map(&RuckSack.priority/1)
|> Enum.sum()
Day 4: Part 1
day_four_input_url = "https://adventofcode.com/2022/day/4/input"
day_four_input = get_input.(day_four_input_url)
defmodule Assignments do
def overlap(input) do
{a, b} =
input
|> Enum.chunk_every(2)
|> Enum.map(fn [from, to] -> MapSet.new(Range.new(from, to)) end)
|> List.to_tuple()
MapSet.subset?(a, b) || MapSet.subset?(b, a)
end
end
day_four_input
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, "-") end)
|> Enum.filter(fn a -> a != "" end)
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(4)
|> Enum.map(&Assignments.overlap/1)
|> Enum.filter(&Function.identity/1)
|> Enum.count()
Day 4: Part 2
defmodule Assignments do
def intersect(input) do
input
|> Enum.chunk_every(2)
|> Enum.map(fn [from, to] -> MapSet.new(Range.new(from, to)) end)
|> then(fn [a, b] -> MapSet.intersection(a, b) end)
|> Enum.empty?()
|> Kernel.not()
end
end
day_four_input
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, ",") end)
|> Enum.flat_map(fn a -> String.split(a, "-") end)
|> Enum.filter(fn a -> a != "" end)
|> Enum.map(&String.to_integer/1)
|> Enum.chunk_every(4)
|> Enum.map(&Assignments.intersect/1)
|> Enum.filter(&Function.identity/1)
|> Enum.count()