solve 2024 day 8
This commit is contained in:
parent
6db60b7f34
commit
75dd6aec6d
4 changed files with 82 additions and 2 deletions
|
@ -3,7 +3,7 @@
|
|||
| S | M | T | W | T | F | S |
|
||||
| :-: | :-: | :-: | :-: | :-: | :-: | :-: |
|
||||
| [1] | [2] | [3] | [4] | [5] | [6] | [7] |
|
||||
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
|
||||
| [8] | 9 | 10 | 11 | 12 | 13 | 14 |
|
||||
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
|
||||
| 22 | 23 | 24 | 25 | | | |
|
||||
|
||||
|
@ -14,3 +14,4 @@
|
|||
[5]: ./lib/2024/5.ex
|
||||
[6]: ./lib/2024/6.ex
|
||||
[7]: ./lib/2024/7.ex
|
||||
[8]: ./lib/2024/8.ex
|
||||
|
|
59
2024/lib/2024/8.ex
Normal file
59
2024/lib/2024/8.ex
Normal file
|
@ -0,0 +1,59 @@
|
|||
import AOC
|
||||
import AOC.Prelude
|
||||
|
||||
aoc 2024, 8 do
|
||||
def p1(input) do
|
||||
input
|
||||
|> map_grid()
|
||||
|> count_antinodes(&antinodes_for_tower_pair/1)
|
||||
end
|
||||
|
||||
def p2(input) do
|
||||
grid = map_grid(input)
|
||||
|
||||
count_antinodes(grid, &resonant_harmonics_antinodes_for_tower_pair(&1, grid))
|
||||
end
|
||||
|
||||
##
|
||||
|
||||
defp count_antinodes(grid, antinodes_for_tower_fun) do
|
||||
grid
|
||||
|> find_tower_pairs()
|
||||
|> Enum.map(&elem(&1, 0))
|
||||
|> Enum.flat_map(antinodes_for_tower_fun)
|
||||
|> Enum.filter(&in_bounds?(grid, &1))
|
||||
|> Enum.uniq()
|
||||
|> Enum.count()
|
||||
end
|
||||
|
||||
defp find_tower_pairs(grid) do
|
||||
tower_locaions = Map.reject(grid, &match?({_, "."}, &1))
|
||||
|
||||
for {pos_a, t} <- tower_locaions, {pos_b, ^t} <- tower_locaions, pos_a != pos_b, into: %{} do
|
||||
{[pos_a, pos_b]
|
||||
|> Enum.sort()
|
||||
|> List.to_tuple(), t}
|
||||
end
|
||||
end
|
||||
|
||||
defp antinodes_for_tower_pair({pos_a, pos_b}) do
|
||||
d = delta(pos_a, pos_b)
|
||||
|
||||
[sub_delta(pos_a, d), add_delta(pos_b, d)]
|
||||
end
|
||||
|
||||
defp resonant_harmonics_antinodes_for_tower_pair({pos_a, pos_b}, grid) do
|
||||
d = delta(pos_a, pos_b)
|
||||
|
||||
sub_stream = pos_a |> Stream.iterate(&sub_delta(&1, d)) |> Stream.take_while(&in_bounds?(grid, &1))
|
||||
add_stream = pos_b |> Stream.iterate(&add_delta(&1, d)) |> Stream.take_while(&in_bounds?(grid, &1))
|
||||
|
||||
sub_stream
|
||||
|> Stream.concat(add_stream)
|
||||
|> Enum.to_list()
|
||||
end
|
||||
|
||||
defp delta({x1, y1}, {x2, y2}), do: {x2 - x1, y2 - y1}
|
||||
defp add_delta({x, y}, {xd, yd}), do: {x + xd, y + yd}
|
||||
defp sub_delta({x, y}, {xd, yd}), do: {x - xd, y - yd}
|
||||
end
|
|
@ -27,4 +27,24 @@ defmodule AOC.Prelude do
|
|||
|> String.split(separator, trim: true)
|
||||
|> Enum.map(&String.to_integer/1)
|
||||
end
|
||||
|
||||
@type map_grid(a) :: %{{x :: non_neg_integer(), y :: non_neg_integer()} => a}
|
||||
|
||||
@doc """
|
||||
Reads an Advent of Code-style grid of characters into a map of x, y positions
|
||||
to a string containing the single character at that position.
|
||||
"""
|
||||
@spec map_grid(String.t()) :: map_grid(String.t())
|
||||
def map_grid(input) do
|
||||
for {line, y} <- Enum.with_index(lines(input)), {c, x} <- Enum.with_index(String.graphemes(line)), into: %{} do
|
||||
{{x, y}, c}
|
||||
end
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns `true` if the given position tuple is within the bounds of the
|
||||
map_grid.
|
||||
"""
|
||||
@spec in_bounds?(map_grid(any()), {x :: integer(), y :: integer()}) :: boolean()
|
||||
def in_bounds?(grid, pos), do: Map.has_key?(grid, pos)
|
||||
end
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
| [2021] | **43/50** 🌟 | Elixir |
|
||||
| [2022] | **14/50** 🌟 | Elixir, Haskell |
|
||||
| [2023] | **19/50** 🌟 | Elixir, Haskell |
|
||||
| [2024] | **14/50** 🌟 | Elixir |
|
||||
| [2024] | **16/50** 🌟 | Elixir |
|
||||
| **Total** | **162** 🌟| |
|
||||
|
||||
[2015]: ./2015
|
||||
|
|
Loading…
Reference in a new issue