diff --git a/advent-of-code/2024/day_08/README.md b/advent-of-code/2024/day_08/README.md new file mode 100644 index 0000000..988b1ea --- /dev/null +++ b/advent-of-code/2024/day_08/README.md @@ -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? diff --git a/advent-of-code/2024/day_08/input.txt b/advent-of-code/2024/day_08/input.txt new file mode 100644 index 0000000..fdb3cf5 --- /dev/null +++ b/advent-of-code/2024/day_08/input.txt @@ -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........ diff --git a/advent-of-code/2024/day_08/lib.rb b/advent-of-code/2024/day_08/lib.rb new file mode 100644 index 0000000..58a21bf --- /dev/null +++ b/advent-of-code/2024/day_08/lib.rb @@ -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 diff --git a/advent-of-code/2024/day_08/main.rb b/advent-of-code/2024/day_08/main.rb new file mode 100644 index 0000000..298edde --- /dev/null +++ b/advent-of-code/2024/day_08/main.rb @@ -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}") diff --git a/advent-of-code/2024/day_08/test.rb b/advent-of-code/2024/day_08/test.rb new file mode 100644 index 0000000..ad163c9 --- /dev/null +++ b/advent-of-code/2024/day_08/test.rb @@ -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 diff --git a/advent-of-code/2024/day_08/test.txt b/advent-of-code/2024/day_08/test.txt new file mode 100644 index 0000000..78a1e91 --- /dev/null +++ b/advent-of-code/2024/day_08/test.txt @@ -0,0 +1,12 @@ +............ +........0... +.....0...... +.......0.... +....0....... +......A..... +............ +............ +........A... +.........A.. +............ +............