Day 3
This commit is contained in:
parent
77ef527041
commit
16f5505974
|
@ -0,0 +1,86 @@
|
||||||
|
defmodule Day3 do
|
||||||
|
|
||||||
|
defmodule Rect do
|
||||||
|
defstruct [:id, :left, :top, :width, :height]
|
||||||
|
|
||||||
|
def points(nil), do: []
|
||||||
|
def points(rect) do
|
||||||
|
xs = rect.left..(rect.left + rect.width - 1)
|
||||||
|
Enum.flat_map(xs, fn x ->
|
||||||
|
ys = rect.top..(rect.top + rect.height - 1)
|
||||||
|
Enum.map(ys, fn y -> {x, y} end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def overlap(a, b) do
|
||||||
|
overlap_left = max(a.left, b.left)
|
||||||
|
overlap_width = max(0, min(a.left + a.width, b.left + b.width) - overlap_left)
|
||||||
|
overlap_top = max(a.top, b.top)
|
||||||
|
overlap_height = max(0, min(a.top + a.height, b.top + b.height) - overlap_top)
|
||||||
|
case overlap_width * overlap_height do
|
||||||
|
0 ->
|
||||||
|
nil
|
||||||
|
_ ->
|
||||||
|
%Rect{left: overlap_left, top: overlap_top, width: overlap_width, height: overlap_height}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_rect(str) do
|
||||||
|
parts = Regex.run(~r/#(\d+) @ (\d+),(\d+): (\d+)x(\d+)/, str)
|
||||||
|
%Rect{
|
||||||
|
id: parts |> Enum.at(1) |> String.to_integer,
|
||||||
|
left: parts |> Enum.at(2) |> String.to_integer,
|
||||||
|
top: parts |> Enum.at(3) |> String.to_integer,
|
||||||
|
width: parts |> Enum.at(4) |> String.to_integer,
|
||||||
|
height: parts |> Enum.at(5) |> String.to_integer,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def except(list, except) do
|
||||||
|
Enum.reject(list, fn el -> el == except end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def overlap_area(rects) do
|
||||||
|
rects
|
||||||
|
|> Enum.flat_map(fn rect ->
|
||||||
|
rects
|
||||||
|
|> except(rect)
|
||||||
|
|> Enum.map(fn other ->
|
||||||
|
Rect.overlap(rect, other)
|
||||||
|
end)
|
||||||
|
|> Enum.flat_map(&Rect.points/1)
|
||||||
|
end)
|
||||||
|
|> Enum.uniq
|
||||||
|
|> Enum.count
|
||||||
|
end
|
||||||
|
|
||||||
|
def exclude_overlapping(rects) do
|
||||||
|
rects
|
||||||
|
|> Enum.reject(fn rect ->
|
||||||
|
rects
|
||||||
|
|> except(rect)
|
||||||
|
|> Enum.any?(fn other ->
|
||||||
|
Rect.overlap(rect, other) != nil
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_input() do
|
||||||
|
File.read!("lib/day3/input.txt")
|
||||||
|
|> String.split("\n", trim: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def part1() do
|
||||||
|
parse_input()
|
||||||
|
|> Enum.map(&parse_rect/1)
|
||||||
|
|> overlap_area()
|
||||||
|
end
|
||||||
|
|
||||||
|
def part2() do
|
||||||
|
parse_input()
|
||||||
|
|> Enum.map(&parse_rect/1)
|
||||||
|
|> exclude_overlapping()
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
||||||
|
defmodule Day3Test do
|
||||||
|
use ExUnit.Case
|
||||||
|
doctest Day3
|
||||||
|
alias Day3.Rect
|
||||||
|
|
||||||
|
test "rect overlap" do
|
||||||
|
a = %Rect{id: 1, left: 1, top: 3, width: 4, height: 4}
|
||||||
|
b = %Rect{id: 2, left: 3, top: 1, width: 4, height: 4}
|
||||||
|
assert Rect.overlap(a, b) == %Rect{id: nil, left: 3, top: 3, width: 2, height: 2}
|
||||||
|
|
||||||
|
a = %Rect{id: 1, left: 0, top: 0, width: 4, height: 4}
|
||||||
|
b = %Rect{id: 2, left: 4, top: 2, width: 4, height: 4}
|
||||||
|
assert Rect.overlap(a, b) == nil
|
||||||
|
end
|
||||||
|
|
||||||
|
test "parse rectangle from string" do
|
||||||
|
assert Day3.parse_rect("#1 @ 1,3: 4x4") == %Rect{id: 1, left: 1, top: 3, width: 4, height: 4}
|
||||||
|
assert Day3.parse_rect("#2 @ 3,1: 4x4") == %Rect{id: 2, left: 3, top: 1, width: 4, height: 4}
|
||||||
|
assert Day3.parse_rect("#3 @ 5,5: 2x2") == %Rect{id: 3, left: 5, top: 5, width: 2, height: 2}
|
||||||
|
end
|
||||||
|
|
||||||
|
test "overlap area" do
|
||||||
|
rects = [
|
||||||
|
%Rect{id: 1, left: 1, top: 3, width: 4, height: 4},
|
||||||
|
%Rect{id: 2, left: 3, top: 1, width: 4, height: 4},
|
||||||
|
%Rect{id: 3, left: 5, top: 5, width: 2, height: 2}
|
||||||
|
]
|
||||||
|
assert Day3.overlap_area(rects) == 4
|
||||||
|
end
|
||||||
|
|
||||||
|
test "exclude overlapping" do
|
||||||
|
rects = [
|
||||||
|
%Rect{id: 1, left: 1, top: 3, width: 4, height: 4},
|
||||||
|
%Rect{id: 2, left: 3, top: 1, width: 4, height: 4},
|
||||||
|
%Rect{id: 3, left: 5, top: 5, width: 2, height: 2}
|
||||||
|
]
|
||||||
|
res = Day3.exclude_overlapping(rects)
|
||||||
|
assert Enum.count(res) == 1
|
||||||
|
assert Enum.at(res, 0).id == 3
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
Reference in New Issue