Solve day 8 of AoC 2024
This commit is contained in:
parent
f6da5e2e12
commit
0c6bf7e054
6 changed files with 319 additions and 0 deletions
152
advent-of-code/2024/day_08/README.md
Normal file
152
advent-of-code/2024/day_08/README.md
Normal file
|
@ -0,0 +1,152 @@
|
|||
# Day 8: Resonant Collinearity
|
||||
|
||||
[Advent of Code 2024](https://adventofcode.com/2024/day/8)
|
||||
|
||||
You find yourselves on the roof of a top-secret Easter Bunny installation.
|
||||
|
||||
While The Historians do their thing, you take a look at the familiar huge antenna.
|
||||
Much to your surprise, it seems to have been reconfigured to emit a signal that makes people 0.1% more likely to buy
|
||||
Easter Bunny brand Imitation Mediocre Chocolate as a Christmas gift! Unthinkable!
|
||||
|
||||
Scanning across the city, you find that there are actually many such antennas.
|
||||
Each antenna is tuned to a specific frequency indicated by a single lowercase letter, uppercase letter, or digit.
|
||||
You create a map (your puzzle input) of these antennas. For example:
|
||||
|
||||
```
|
||||
............
|
||||
........0...
|
||||
.....0......
|
||||
.......0....
|
||||
....0.......
|
||||
......A.....
|
||||
............
|
||||
............
|
||||
........A...
|
||||
.........A..
|
||||
............
|
||||
............
|
||||
```
|
||||
|
||||
The signal only applies its nefarious effect at specific antinodes based on the resonant frequencies of the antennas.
|
||||
In particular, an antinode occurs at any point that is perfectly in line with two antennas of the same frequency - but only when
|
||||
one of the antennas is twice as far away as the other. This means that for any pair of antennas with the same frequency,
|
||||
there are two antinodes, one on either side of them.
|
||||
|
||||
So, for these two antennas with frequency a, they create the two antinodes marked with #:
|
||||
|
||||
```
|
||||
..........
|
||||
...#......
|
||||
..........
|
||||
....a.....
|
||||
..........
|
||||
.....a....
|
||||
..........
|
||||
......#...
|
||||
..........
|
||||
..........
|
||||
```
|
||||
|
||||
Adding a third antenna with the same frequency creates several more antinodes. It would ideally add four antinodes,
|
||||
but two are off the right side of the map, so instead it adds only two:
|
||||
|
||||
```
|
||||
..........
|
||||
...#......
|
||||
#.........
|
||||
....a.....
|
||||
........a.
|
||||
.....a....
|
||||
..#.......
|
||||
......#...
|
||||
..........
|
||||
..........
|
||||
```
|
||||
|
||||
Antennas with different frequencies don't create antinodes; A and a count as different frequencies.
|
||||
However, antinodes can occur at locations that contain antennas. In this diagram, the lone antenna with frequency capital A
|
||||
creates no antinodes but has a lowercase-a-frequency antinode at its location:
|
||||
|
||||
```
|
||||
..........
|
||||
...#......
|
||||
#.........
|
||||
....a.....
|
||||
........a.
|
||||
.....a....
|
||||
..#.......
|
||||
......A...
|
||||
..........
|
||||
..........
|
||||
```
|
||||
|
||||
The first example has antennas with two different frequencies, so the antinodes they create look like this,
|
||||
plus an antinode overlapping the topmost A-frequency antenna:
|
||||
|
||||
```
|
||||
......#....#
|
||||
...#....0...
|
||||
....#0....#.
|
||||
..#....0....
|
||||
....0....#..
|
||||
.#....A.....
|
||||
...#........
|
||||
#......#....
|
||||
........A...
|
||||
.........A..
|
||||
..........#.
|
||||
..........#.
|
||||
```
|
||||
|
||||
Because the topmost A-frequency antenna overlaps with a 0-frequency antinode, there are 14 total unique locations
|
||||
that contain an antinode within the bounds of the map.
|
||||
|
||||
Calculate the impact of the signal. How many unique locations within the bounds of the map contain an antinode?
|
||||
|
||||
|
||||
## Part Two
|
||||
|
||||
Watching over your shoulder as you work, one of The Historians asks if you took the effects of resonant harmonics into your calculations.
|
||||
|
||||
Whoops!
|
||||
|
||||
After updating your model, it turns out that an antinode occurs at any grid position exactly in line with at least two antennas
|
||||
of the same frequency, regardless of distance. This means that some of the new antinodes will occur at the position
|
||||
of each antenna (unless that antenna is the only one of its frequency).
|
||||
|
||||
So, these three T-frequency antennas now create many antinodes:
|
||||
|
||||
```
|
||||
T....#....
|
||||
...T......
|
||||
.T....#...
|
||||
.........#
|
||||
..#.......
|
||||
..........
|
||||
...#......
|
||||
..........
|
||||
....#.....
|
||||
..........
|
||||
```
|
||||
|
||||
In fact, the three T-frequency antennas are all exactly in line with two antennas, so they are all also antinodes!
|
||||
This brings the total number of antinodes in the above example to 9.
|
||||
|
||||
The original example now has 34 antinodes, including the antinodes that appear on every antenna:
|
||||
|
||||
```
|
||||
##....#....#
|
||||
.#.#....0...
|
||||
..#.#0....#.
|
||||
..##...0....
|
||||
....0....#..
|
||||
.#...#A....#
|
||||
...#..#.....
|
||||
#....#.#....
|
||||
..#.....A...
|
||||
....#....A..
|
||||
.#........#.
|
||||
...#......##
|
||||
```
|
||||
|
||||
Calculate the impact of the signal using this updated model. How many unique locations within the bounds of the map contain an antinode?
|
50
advent-of-code/2024/day_08/input.txt
Normal file
50
advent-of-code/2024/day_08/input.txt
Normal file
|
@ -0,0 +1,50 @@
|
|||
..........M..........j.............y.....O........
|
||||
...B...............q......m........lGO............
|
||||
....................q......2.l.GQ...O.............
|
||||
.....X.......................................4....
|
||||
.....................q............................
|
||||
....M......P...............xl.K.............2.....
|
||||
....F.........L.......C.K..............m..........
|
||||
..........FM......P....jy......m..........o...r...
|
||||
..X.......P.....RL..............G..x..........4...
|
||||
............L..........NC.....q...................
|
||||
.....C.X...............K....y..........4..........
|
||||
........S...R.............j.x.....V...4...........
|
||||
.....................R..x.....V..i......m.........
|
||||
...........................R.V......N.......X.....
|
||||
.....F.........M......N......E....................
|
||||
................v................T.......F......O.
|
||||
.............................N...V.......Q........
|
||||
...v.....................C.....i..................
|
||||
......c.....W..n.w........................E.......
|
||||
3...................c.....................Q..6....
|
||||
...........h......................j...............
|
||||
.......n.0......h.................E..............2
|
||||
.v.............7.......120.....c..................
|
||||
......n.0............w...........D.t.........E...r
|
||||
....8..3......0.w.hP....z...D..T...............r..
|
||||
.................f........T........G......eQ......
|
||||
......f.n.....7..p................................
|
||||
.....Y..7.......f......I......D......K............
|
||||
............Uf....T..W.....D..r...i...............
|
||||
......I...............................Z...........
|
||||
....5....B.......b..............s..............Z..
|
||||
..........d...W..Uwh.............c..........i.....
|
||||
..I.3..Y......................e...................
|
||||
.....p.b..........k......7........................
|
||||
p...........k....I..b..........s..................
|
||||
.....k.......o...........W........................
|
||||
.A..Y..........U.................a........6.......
|
||||
..A...Y.p...................................6.....
|
||||
B......k..........................Z............u..
|
||||
...3.....................s..............a.........
|
||||
......A.........................g.....a...........
|
||||
.......A....8...b.U......H....sS..................
|
||||
.........................S1.............t.........
|
||||
.....................9z..e.....5..1.g.u...........
|
||||
.......................z....d....g....H.J....o.6..
|
||||
........B................d.....u....9.J.H.........
|
||||
.8........S.................u9.............J.....H
|
||||
.....................Z5.............t1...........a
|
||||
.....................e..v...................o..t..
|
||||
.....8...............L.....z.............J........
|
83
advent-of-code/2024/day_08/lib.rb
Normal file
83
advent-of-code/2024/day_08/lib.rb
Normal file
|
@ -0,0 +1,83 @@
|
|||
class Vec2
|
||||
attr_accessor :x, :y
|
||||
|
||||
def initialize(x, y)
|
||||
@x = x
|
||||
@y = y
|
||||
end
|
||||
end
|
||||
|
||||
def count_antinodes(matrix, limit_length)
|
||||
station_coords = extract_stations(matrix)
|
||||
|
||||
# Create zero matrix.
|
||||
antinodes = Array.new(matrix.length) { Array.new(matrix[0].length, 0) }
|
||||
|
||||
station_coords.each_value do |loc|
|
||||
(0..loc.length - 2).each do |i|
|
||||
(i + 1..loc.length - 1).each do |j|
|
||||
x_diff = loc[j].x - loc[i].x
|
||||
y_diff = loc[j].y - loc[i].y
|
||||
|
||||
x1 = loc[i].x - x_diff
|
||||
y1 = loc[i].y - y_diff
|
||||
while in_range?(matrix, x1, y1)
|
||||
antinodes[x1][y1] += 1
|
||||
break if limit_length
|
||||
|
||||
x1 -= x_diff
|
||||
y1 -= y_diff
|
||||
end
|
||||
|
||||
x2 = loc[j].x + x_diff
|
||||
y2 = loc[j].y + y_diff
|
||||
while in_range?(matrix, x2, y2)
|
||||
antinodes[x2][y2] += 1
|
||||
break if limit_length
|
||||
|
||||
x2 += x_diff
|
||||
y2 += y_diff
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
unless limit_length
|
||||
station_coords.each_value do |locations|
|
||||
locations.each do |loc|
|
||||
antinodes[loc.x][loc.y] += 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
count = 0
|
||||
antinodes.each do |row|
|
||||
row.each do |value|
|
||||
next if value.zero?
|
||||
|
||||
count += 1
|
||||
end
|
||||
end
|
||||
|
||||
count
|
||||
end
|
||||
|
||||
def in_range?(matrix, x, y)
|
||||
x >= 0 and y >= 0 and x < matrix.length and y < matrix[x].length
|
||||
end
|
||||
|
||||
def extract_stations(matrix)
|
||||
station_coords = {}
|
||||
|
||||
(0..matrix.length - 1).each do |x|
|
||||
(0..matrix[x].length - 1).each do |y|
|
||||
ch = matrix[x][y]
|
||||
next if ch == '.'
|
||||
|
||||
station_coords[ch] = [] unless station_coords.include?(ch)
|
||||
station_coords[ch].push(Vec2.new(x, y))
|
||||
end
|
||||
end
|
||||
|
||||
station_coords
|
||||
end
|
8
advent-of-code/2024/day_08/main.rb
Normal file
8
advent-of-code/2024/day_08/main.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
require_relative "lib.rb"
|
||||
|
||||
input = File.readlines('input.txt', chomp: true)
|
||||
res1 = count_antinodes(input, true)
|
||||
puts("Part 1: #{res1}")
|
||||
|
||||
res2 = count_antinodes(input, false)
|
||||
puts("Part 2: #{res2}")
|
14
advent-of-code/2024/day_08/test.rb
Normal file
14
advent-of-code/2024/day_08/test.rb
Normal file
|
@ -0,0 +1,14 @@
|
|||
require_relative "lib.rb"
|
||||
require "test/unit"
|
||||
|
||||
class TestAntinodeCounter < Test::Unit::TestCase
|
||||
def test_part_1
|
||||
input = File.readlines("test.txt", chomp: true)
|
||||
assert_equal(14, count_antinodes(input, true))
|
||||
end
|
||||
|
||||
def test_part_2
|
||||
input = File.readlines("test.txt", chomp: true)
|
||||
assert_equal(34, count_antinodes(input, false))
|
||||
end
|
||||
end
|
12
advent-of-code/2024/day_08/test.txt
Normal file
12
advent-of-code/2024/day_08/test.txt
Normal file
|
@ -0,0 +1,12 @@
|
|||
............
|
||||
........0...
|
||||
.....0......
|
||||
.......0....
|
||||
....0.......
|
||||
......A.....
|
||||
............
|
||||
............
|
||||
........A...
|
||||
.........A..
|
||||
............
|
||||
............
|
Loading…
Reference in a new issue