Advent of Code 2022
Mix.install([
{:req, "~> 0.3.2"}
])
Day 4
input =
"https://adventofcode.com/2022/day/4/input"
|> Req.get!(headers: [cookie: "session=#{System.get_env("AOC_COOKIE")}"])
|> Map.get(:body)
Part 1
input
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
line
|> String.split(",")
|> Enum.map(fn pair ->
pair
|> String.split("-")
|> Enum.map(&String.to_integer(&1))
end)
end)
|> Enum.filter(fn [[x1, y1], [x2, y2]] ->
(x1 <= x2 && y1 >= y2) || (x2 <= x1 && y2 >= y1)
end)
|> Enum.count()
input
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
line
|> String.split(",")
|> Enum.map(fn pair ->
pair
|> String.split("-")
|> Enum.map(&String.to_integer(&1))
end)
end)
|> Enum.filter(fn [[x1, y1], [x2, y2]] ->
a = MapSet.new(Range.new(x1, y1))
b = MapSet.new(Range.new(x2, y2))
MapSet.subset?(a, b) || MapSet.subset?(b, a)
end)
|> Enum.count()
Part 2
input
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
line
|> String.split(",")
|> Enum.map(fn pair ->
pair
|> String.split("-")
|> Enum.map(&String.to_integer(&1))
end)
end)
|> Enum.filter(fn [[x1, y1], [x2, y2]] ->
(x1 >= x2 && x1 <= y2) || (y1 >= x2 && y1 <= y2) || (x2 >= x1 && x2 <= y1) ||
(y2 >= x1 && y2 <= y1)
end)
|> Enum.count()
Alternate Solutions
Parse using regex and convert to ranges:
lines =
input
|> String.split("\n", trim: true)
|> Enum.map(fn line ->
Regex.run(~r/(\d+)-(\d+),(\d+)-(\d+)/, line)
|> tl()
|> Enum.map(&String.to_integer/1)
|> then(fn [a, b, c, d] -> {a..b, c..d} end)
end)
For part 1, use MapSet.subset?:
lines
|> Enum.filter(fn {r1, r2} ->
a = MapSet.new(r1)
b = MapSet.new(r2)
MapSet.subset?(a, b) || MapSet.subset?(b, a)
end)
|> Enum.count()
For part 2, use Range.disjoint?/2:
lines
|> Enum.filter(fn {r1, r2} ->
!Range.disjoint?(r1, r2)
end)
|> Enum.count()