66 lines
1.4 KiB
Elixir
66 lines
1.4 KiB
Elixir
import AOC
|
|
|
|
aoc 2021, 5 do
|
|
import NimbleParsec
|
|
|
|
defparsec(
|
|
:vent_readout_parsec,
|
|
integer(min: 1)
|
|
|> ignore(string(","))
|
|
|> integer(min: 1)
|
|
|> ignore(string(" -> "))
|
|
|> integer(min: 1)
|
|
|> ignore(string(","))
|
|
|> integer(min: 1)
|
|
)
|
|
|
|
def parse_vent_readout(line) do
|
|
{:ok, [x1, y1, x2, y2], _, _, _, _} = line |> vent_readout_parsec()
|
|
|
|
{{x1, y1}, {x2, y2}}
|
|
end
|
|
|
|
def input_stream(), do: super() |> Stream.map(&parse_vent_readout/1)
|
|
|
|
def p1 do
|
|
input_stream()
|
|
|> Enum.reduce(Map.new(), &record_line_on_map(&1, &2, false))
|
|
|> Map.values()
|
|
|> Enum.count(&(&1 > 1))
|
|
end
|
|
|
|
def p2 do
|
|
input_stream()
|
|
|> Enum.reduce(Map.new(), &record_line_on_map(&1, &2, true))
|
|
|> Map.values()
|
|
|> Enum.count(&(&1 > 1))
|
|
end
|
|
|
|
def record_line_on_map(line, map, include_diagonals),
|
|
do:
|
|
map
|
|
|> record_points_on_map(points_on_line(line, include_diagonals))
|
|
|
|
def record_points_on_map(map, points) do
|
|
for point <- points, reduce: map do
|
|
map -> Map.update(map, point, 1, &(&1 + 1))
|
|
end
|
|
end
|
|
|
|
# vertical lines
|
|
def points_on_line({{x, y1}, {x, y2}}, _) do
|
|
for y <- y1..y2, do: {x, y}
|
|
end
|
|
|
|
# horizontal lines
|
|
def points_on_line({{x1, y}, {x2, y}}, _) do
|
|
for x <- x1..x2, do: {x, y}
|
|
end
|
|
|
|
# diagonal lines
|
|
def points_on_line({{x1, y1}, {x2, y2}}, true) do
|
|
Enum.zip(x1..x2, y1..y2)
|
|
end
|
|
|
|
def points_on_line(_, false), do: []
|
|
end
|