diff --git a/2025/ruby/day_04.rb b/2025/ruby/day_04.rb
new file mode 100644
index 0000000..da8ce71
--- /dev/null
+++ b/2025/ruby/day_04.rb
@@ -0,0 +1,44 @@
+NEIGHBORS = [
+ [-1,-1], [-1,0], [-1,1],
+ [ 0,-1], [ 0,1],
+ [ 1,-1], [ 1,0], [1 ,1],
+]
+
+Grid = Data.define(:rolls) do
+ def size = rolls.size
+
+ def accessible
+ rolls.select {|(y,x)|
+ NEIGHBORS.count {|(dy,dx)|
+ rolls.include?([y+dy, x+dx])
+ } < 4
+ }
+ end
+
+ def removed
+ return enum_for(__method__) unless block_given?
+
+ grid = self
+ loop do
+ yield grid
+ grid = Grid.new(grid.rolls - grid.accessible)
+ end
+ end
+end
+
+grid = Grid.new(
+ DATA.read
+ .lines(chomp: true)
+ .each.with_index.inject(Set.new) do |rolls, (line, y)|
+ rolls.merge(
+ line.chars.each.with_index
+ .select {|roll,_| roll == ?@ }
+ .map { [y, _2] }
+ )
+ end
+)
+
+chunk = grid.removed.slice_when { _1.size == _2.size }.next
+pp chunk.first.size - chunk.last.size
+
+__END__