diff options
Diffstat (limited to 'src/day08.exs')
-rw-r--r-- | src/day08.exs | 72 |
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 |