Add solutions for 2022:4-5

This commit is contained in:
Anders Englöf Ytterström 2022-12-05 23:17:30 +01:00 committed by Anders Englöf Ytterström
parent 93d014893f
commit c98303d0c1
4 changed files with 242 additions and 0 deletions

View file

@ -0,0 +1,57 @@
defmodule Aoc.Solution.Day04 do
import Aoc.Utils
@name "Day 4: Camp Cleanup"
@behaviour Solution
@impl Solution
def get_name, do: @name
@impl Solution
def present(solution), do: "#{solution} assignment pairs overlap"
@impl Solution
def present_again(solution), do: "Solution is #{solution}"
@impl Solution
def parse!(raw) do
raw
|> split_lines()
|> Enum.map(fn l -> parse_values(l, ",") end)
end
@impl Solution
def solve(pairs) do
pairs
|> ranges()
|> overlaps()
|> Enum.count()
end
@impl Solution
def solve_again(pairs) do
pairs
|> ranges()
|> strict_overlaps()
|> Enum.count()
end
def ranges(rows) when length(rows) > 2 do
Enum.map(rows, &ranges/1)
end
def ranges(pairs) do
Enum.map(pairs, fn p ->
[start, stop] = parse_values(p, "-") |> Enum.map(&String.to_integer/1)
MapSet.new(start..stop)
end)
end
def overlaps(ranges), do: Enum.filter(ranges, &overlap?/1)
def overlap?([a, b]), do: MapSet.subset?(a, b) or MapSet.subset?(b, a)
def strict_overlaps(ranges), do: Enum.filter(ranges, &strict_overlap?/1)
def strict_overlap?([a, b]), do: MapSet.intersection(a, b) |> Enum.count() > 0
end

View file

@ -0,0 +1,122 @@
defmodule Aoc.Solution.Day05 do
import Aoc.Utils
@name "Day 5: Supply Stacks"
@behaviour Solution
@impl Solution
def get_name, do: @name
@impl Solution
def present(solution), do: "On 9000, top crate on each stack is #{solution}"
@impl Solution
def present_again(solution), do: "On 9001, top crate on each stack is #{solution}"
@impl Solution
def parse!(raw) do
[initial_state, instructions] = raw |> String.split("\n\n")
{
initial_state |> String.split("\n") |> Enum.drop(-1) |> parse_state(),
instructions |> String.trim() |> split_lines() |> parse_instructions()
}
end
@impl Solution
def solve({state, instructions}) do
state
|> move(instructions, 9000)
|> topmost()
end
@impl Solution
def solve_again({state, instructions}) do
state
|> move(instructions, 9001)
|> topmost()
end
def parse_state(state) do
blank = "[-]"
len = Enum.map(state, &String.length/1) |> Enum.max()
Enum.map(state, fn line ->
line
|> String.pad_trailing(len)
|> String.pad_leading(len + 1)
|> String.replace(" ", " #{blank}")
end)
|> Enum.map(fn l ->
l
|> String.trim()
|> String.split()
end)
|> Enum.zip()
|> Enum.map(fn t ->
t
|> Tuple.to_list()
|> Enum.reject(fn v -> v == blank end)
|> Enum.map(fn v ->
v
|> String.slice(1..-2)
end)
end)
end
def parse_instructions(lines) do
Enum.map(lines, fn "move " <> line ->
[steps, _f, from, _t, to] = String.split(line)
Enum.map([steps, from, to], &String.to_integer/1)
end)
end
def move(state, [], _), do: state
def move(state, [[n, from, to] | remaining], model) do
move(
case model do
9000 -> _move_9000(state, from - 1, to - 1, n)
9001 -> _move_9001(state, from - 1, to - 1, n)
end,
remaining,
model
)
end
def _move_9001(state, from, to, n) do
{pre, rem} = state |> Enum.at(from) |> Enum.split(n)
state
|> List.update_at(from, fn _ -> rem end)
|> List.update_at(to, fn l -> pre ++ l end)
end
def _move_9000(state, _from, _to, 0) do
state
end
def _move_9000(state, from, to, n) do
case Enum.at(state, from) do
[a | rem] ->
_move_9000(
state
|> List.update_at(from, fn _ -> rem end)
|> List.update_at(to, fn l -> [a | l] end),
from,
to,
n - 1
)
[] ->
state
nil ->
state
end
end
def topmost(state) do
state |> Enum.map(&List.first/1) |> Enum.join("")
end
end

View file

@ -0,0 +1,30 @@
defmodule Day04Test do
use ExUnit.Case
doctest Aoc.Solution.Day04
import Aoc.Solution.Day04
@input ~s(
2-4,6-8
2-3,4-5
5-7,7-9
2-8,3-7
6-6,4-6
2-6,4-8
)
test "04: Camp Cleanup, part 1" do
expected = 2
result = @input |> parse!() |> solve()
assert result == expected
end
test "04: Camp Cleanup, part 2" do
expected = 4
result = @input |> parse!() |> solve_again()
assert result == expected
end
end

View file

@ -0,0 +1,33 @@
defmodule Day05Test do
use ExUnit.Case
doctest Aoc.Solution.Day05
import Aoc.Solution.Day05
@input ~s(
[D]
[N] [C]
[Z] [M] [P]
1 2 3
move 1 from 2 to 1
move 3 from 1 to 3
move 2 from 2 to 1
move 1 from 1 to 2
)
test "05: Supply Stacks, part 1" do
expected = "CMZ"
result = @input |> parse!() |> solve()
assert result == expected
end
test "05: Supply Stacks, part 2" do
expected = "MCD"
result = @input |> parse!() |> solve_again()
assert result == expected
end
end