74 lines
2 KiB
Elixir
74 lines
2 KiB
Elixir
|
defmodule Three do
|
||
|
@dimension_parser ~r/\#(\d+)\s@\s(\d+),(\d+):\s(\d+)x(\d+)/
|
||
|
|
||
|
def part1(input_stream) do
|
||
|
input_stream
|
||
|
|> Stream.map(&parse_dimensions/1)
|
||
|
|> Stream.map(&points_in_square/1)
|
||
|
|> Enum.to_list()
|
||
|
|> Enum.reduce({MapSet.new([]), MapSet.new([])}, &intersecting_squares/2)
|
||
|
|> elem(1)
|
||
|
|> MapSet.to_list()
|
||
|
|> length()
|
||
|
end
|
||
|
|
||
|
def parse_dimensions(str) do
|
||
|
l = Regex.run(@dimension_parser, str)
|
||
|
[id, x, y, w, h] = l |> tl() |> Enum.map(&String.to_integer/1)
|
||
|
{id, x, y, w, h}
|
||
|
end
|
||
|
|
||
|
def points_in_square({_, x, y, w, h}) do
|
||
|
x..(x + w - 1)
|
||
|
|> Enum.reduce([], fn x, x_set ->
|
||
|
y..(y + h - 1)
|
||
|
|> Enum.reduce(x_set, fn y, xy_set ->
|
||
|
[{x, y} | xy_set]
|
||
|
end)
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
def intersecting_squares(square_set, {set, intersects}) do
|
||
|
square_set
|
||
|
|> Enum.reduce({set, intersects}, fn pos, {set, intersects} ->
|
||
|
case MapSet.member?(set, pos) do
|
||
|
true -> {set, MapSet.put(intersects, pos)}
|
||
|
_ -> {MapSet.put(set, pos), intersects}
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
def intersecting_squares2({id, square_set}, {set, intersects}) do
|
||
|
square_set
|
||
|
|> Enum.reduce({set, intersects}, fn pos, {set, intersects} ->
|
||
|
case MapSet.member?(set, pos) do
|
||
|
true -> {set, MapSet.put(intersects, pos)}
|
||
|
_ -> {MapSet.put(set, pos), intersects}
|
||
|
end
|
||
|
end)
|
||
|
end
|
||
|
|
||
|
# parse input lines
|
||
|
# for each set of dimensions, check each point in the square
|
||
|
# if the point has been recorded already, remove both ids from the set
|
||
|
|
||
|
def part2(input_stream) do
|
||
|
square_data =
|
||
|
input_stream
|
||
|
|> Stream.map(&parse_dimensions/1)
|
||
|
|
||
|
square_id_set =
|
||
|
square_data
|
||
|
|> Stream.map(&elem(&1, 0))
|
||
|
|> Enum.to_list()
|
||
|
|> MapSet.new()
|
||
|
|
||
|
square_data
|
||
|
|> Enum.map(&{elem(&1, 0), points_in_square(&1)})
|
||
|
|> Enum.reduce({MapSet.new([]), square_id_set}, fn {id, points}, acc -> intersecting_squares2({id, points}, ))
|
||
|
|> elem(1)
|
||
|
|> MapSet.to_list()
|
||
|
|> length()
|
||
|
end
|
||
|
end
|