summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/day08.exs72
1 files changed, 30 insertions, 42 deletions
diff --git a/src/day08.exs b/src/day08.exs
index 0d312e1..55ad921 100644
--- a/src/day08.exs
+++ b/src/day08.exs
@@ -1,3 +1,15 @@
+defmodule Utils do
+ def comb(acc \\ [], l, 2) do
+ case l do
+ [h | t] ->
+ Enum.reduce(t, acc, fn x, acc -> [{h, x} | acc] end)
+ |> comb(t, 2)
+ _ ->
+ acc
+ end
+ end
+end
+
defmodule Day08 do
defmodule Grid do
defstruct [:grid, :height, :width]
@@ -39,82 +51,58 @@ defmodule Day08 do
grid = data
|> Grid.from_data()
- antennas = grid
+ grid
|> Grid.find_elements(~r/[[:alnum:]]/)
|> Enum.group_by(fn {k, _, _} -> k end, fn {_, i, j} -> {i, j} end)
-
- antennas
- |> Enum.map(fn {_, a} -> antinodes([], a) end)
- |> Enum.flat_map(& &1)
+ |> Enum.flat_map(fn {_, antennas} -> antinodes1(antennas, grid) end)
|> Enum.uniq()
- |> Enum.filter(fn {i, j} -> Grid.in?(grid, i, j) end)
|> Enum.count()
end
- defp antinodes(acc, [a | rest]) do
- rest
- |> Enum.reduce(acc, fn b, acc -> antinodes(acc, a, b) end)
- |> antinodes(rest)
- end
-
- defp antinodes(acc, []), do: acc
-
- defp antinodes(acc, {ai, aj}, {bi, bj}) do
- di = abs(ai - bi)
- dj = abs(aj - bj)
- [{min(ai, bi) - di, if aj < bj do aj - dj else aj + dj end} |
- [{max(ai, bi) + di, if aj < bj do bj + dj else bj - dj end} |
- acc]]
+ defp antinodes1(antennas, grid) do
+ antennas
+ |> Utils.comb(2)
+ |> Enum.flat_map(fn {{a, b}, {c, d}} -> [{a+a-c, b+b-d}, {c+c-a, d+d-b}] end)
+ |> Enum.filter(fn {a, b} -> Grid.in?(grid, a, b) end)
end
def part2(data) do
grid = data
|> Grid.from_data()
- antennas = grid
+ grid
|> Grid.find_elements(~r/[[:alnum:]]/)
|> Enum.group_by(fn {k, _, _} -> k end, fn {_, i, j} -> {i, j} end)
-
- antennas
- |> Enum.map(fn {_, a} -> antinodes2([], a, grid) end)
- |> Enum.flat_map(& &1)
+ |> Enum.flat_map(fn {_, a} -> antinodes2(a, grid) end)
|> Enum.uniq()
|> Enum.count()
-
end
- defp antinodes2(acc, [a | rest], grid) do
- rest
- |> Enum.reduce(acc, fn b, acc -> antinodes2(acc, a, b, grid) end)
- |> antinodes2(rest, grid)
+ defp antinodes2(antennas, grid) do
+ antennas
+ |> Utils.comb(2)
+ |> Enum.flat_map(fn {a, b} -> antinodes2(a, b, grid) end)
end
- defp antinodes2(acc, [], _), do: acc
-
- defp antinodes2(acc, {ai, aj}, {bi, bj}, grid) do
+ defp antinodes2({ai, aj}, {bi, bj}, grid) do
di = abs(ai - bi)
dj = abs(aj - bj)
cond do
di == 0 ->
- acc
- |> antinodes2(ai, aj, 0, -1, grid)
- |> antinodes2(ai, aj, 0, 1, grid)
+ 0..grid.width-1
dj == 0 ->
- acc
- |> antinodes2(ai, aj, -1, 0, grid)
- |> antinodes2(ai, aj, 1, 0, grid)
+ 0..grid.height-1
true ->
g = Integer.gcd(di, dj)
di = div(di, g)
dj = div(dj, g)
- acc
- |> antinodes2(ai, aj, -di, if aj < bj do -dj else dj end, grid)
+ antinodes2(ai, aj, -di, if aj < bj do -dj else dj end, grid)
|> antinodes2(ai, aj, di, if aj < bj do dj else -dj end, grid)
end
end
- defp antinodes2(acc, i, j, di, dj, grid) do
+ defp antinodes2(acc \\ [], i, j, di, dj, grid) do
if Grid.in?(grid, i, j) do
antinodes2([{i, j} | acc], i+di, j+dj, di, dj, grid)
else