Advent of Code 2022 - Day 4
Mix.install([
{:req_aoc, github: "mcrumm/req_aoc", ref: "eef58c9"}
])
Puzzle description
Day 4: Camp Cleanup.
Solution
defmodule Part1 do
# preflight:
## split string into lines (without break characters)
def run(input) do
input
|> Stream.map(fn line ->
{hr, tr} = to_range_pair(line)
{MapSet.new(hr), MapSet.new(tr)}
end)
|> Stream.filter(fn {hms, tms} ->
MapSet.subset?(hms, tms) or MapSet.subset?(tms, hms)
end)
|> Enum.count()
end
def to_range_pair(line) do
[head, tail] = line |> String.split(",", parts: 2)
[h1, h2] = head |> String.split("-", parts: 2) |> Enum.map(&String.to_integer/1)
[t1, t2] = tail |> String.split("-", parts: 2) |> Enum.map(&String.to_integer/1)
{h1..h2, t1..t2}
end
end
defmodule Part2 do
# preflight:
## split string into lines (without break characters)
def run(input) do
input
|> Stream.map(fn line -> line |> Part1.to_range_pair() end)
|> Stream.filter(fn {hr, tr} -> not Range.disjoint?(hr, tr) end)
|> Enum.count()
end
end
ExUnit.start(autorun: false)
defmodule Test do
use ExUnit.Case, async: true
@example_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
)
@input System.fetch_env!("LB_AOC_SESSION") |> ReqAOC.fetch!({2022, 04}, max_retries: 0)
test "to_range_pair/1" do
assert @example_input
|> to_lines()
|> Enum.map(&Part1.to_range_pair/1) === [
{2..4, 6..8},
{2..3, 4..5},
{5..7, 7..9},
{2..8, 3..7},
{6..6, 4..6},
{2..6, 4..8}
]
end
test "part 1" do
assert @example_input |> to_lines() |> Part1.run() === 2
@input |> to_lines() |> Part1.run() |> dbg()
end
test "part 2" do
assert @example_input |> to_lines() |> Part2.run() === 4
@input |> to_lines() |> Part2.run() |> dbg()
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
ExUnit.configure(trace: true)
ExUnit.run()