83 lines
1.6 KiB
Ruby
83 lines
1.6 KiB
Ruby
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
|