1
0
Fork 0

solve 2024 day 8

This commit is contained in:
sloane 2024-12-08 08:56:51 -05:00
parent 6db60b7f34
commit 75dd6aec6d
Signed by: sloanelybutsurely
SSH key fingerprint: SHA256:8SBnwhl+RY3oEyQxy1a9wByPzxWM0x+/Ejc+sIlY5qQ
4 changed files with 82 additions and 2 deletions

View file

@ -3,7 +3,7 @@
| S | M | T | W | T | F | S | | S | M | T | W | T | F | S |
| :-: | :-: | :-: | :-: | :-: | :-: | :-: | | :-: | :-: | :-: | :-: | :-: | :-: | :-: |
| [1] | [2] | [3] | [4] | [5] | [6] | [7] | | [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 | | 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | | | | | 22 | 23 | 24 | 25 | | | |
@ -14,3 +14,4 @@
[5]: ./lib/2024/5.ex [5]: ./lib/2024/5.ex
[6]: ./lib/2024/6.ex [6]: ./lib/2024/6.ex
[7]: ./lib/2024/7.ex [7]: ./lib/2024/7.ex
[8]: ./lib/2024/8.ex

59
2024/lib/2024/8.ex Normal file
View 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

View file

@ -27,4 +27,24 @@ defmodule AOC.Prelude do
|> String.split(separator, trim: true) |> String.split(separator, trim: true)
|> Enum.map(&String.to_integer/1) |> Enum.map(&String.to_integer/1)
end 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 end

View file

@ -15,7 +15,7 @@
| [2021] | **43/50** 🌟 | Elixir | | [2021] | **43/50** 🌟 | Elixir |
| [2022] | **14/50** 🌟 | Elixir, Haskell | | [2022] | **14/50** 🌟 | Elixir, Haskell |
| [2023] | **19/50** 🌟 | Elixir, Haskell | | [2023] | **19/50** 🌟 | Elixir, Haskell |
| [2024] | **14/50** 🌟 | Elixir | | [2024] | **16/50** 🌟 | Elixir |
| **Total** | **162** 🌟| | | **Total** | **162** 🌟| |
[2015]: ./2015 [2015]: ./2015