Solve day 8 of AoC 2024

This commit is contained in:
Ivan R. 2024-12-13 21:28:39 +05:00
parent f6da5e2e12
commit 0c6bf7e054
Signed by: lumin
GPG key ID: E0937DC7CD6D3817
6 changed files with 319 additions and 0 deletions

View 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?

View 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........

View 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

View 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}")

View 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

View file

@ -0,0 +1,12 @@
............
........0...
.....0......
.......0....
....0.......
......A.....
............
............
........A...
.........A..
............
............