diff --git a/2024/ruby/day_08.rb b/2024/ruby/day_08.rb
new file mode 100644
index 0000000..e2302b5
--- /dev/null
+++ b/2024/ruby/day_08.rb
@@ -0,0 +1,56 @@
+input = DATA
+ .readlines(chomp: true).flat_map.with_index {|row, y|
+ row.chars.map.with_index {|i, x|
+ [[y,x], i]
+ }
+ }.to_h
+
+freqs = input.values.uniq - %w[.]
+pp freqs.flat_map {|freq|
+ antennae = input.select { _2 == freq }.keys
+ antennae.combination(2).flat_map {|(ay,ax),(by,bx)|
+ dy = by - ay
+ dx = bx - ax
+ [[ay-dy, ax-dx], [by+dy, bx+dx]]
+ }.select {|yx| input.has_key?(yx) }
+}.uniq.length
+
+def antinodes(input, a, b)
+ return enum_for(__method__, input, a, b) unless block_given?
+
+ max_y = input.keys.map(&:first).max
+ max_x = input.keys.map(&:last).max
+
+ (ay,ax), (by,bx) = a, b
+
+ dy = by - ay
+ dx = bx - ax
+ r = Rational(dy, dx)
+ dy = r.numerator
+ dx = r.denominator
+
+ y, x = a
+ loop do
+ break unless input.has_key?([y,x])
+ yield [y,x]
+ y -= dy
+ x -= dx
+ end
+
+ y, x = b
+ loop do
+ break unless input.has_key?([y,x])
+ yield [y,x]
+ y += dy
+ x += dx
+ end
+end
+
+pp freqs.flat_map {|freq|
+ antennae = input.select { _2 == freq }.keys
+ antennae.combination(2).flat_map {|a,b|
+ antinodes(input, a, b).to_a
+ }
+}.sort.uniq.length
+
+__END__