diff --git a/2024/ruby/day_18.rb b/2024/ruby/day_18.rb
new file mode 100644
index 0000000..e45ef14
--- /dev/null
+++ b/2024/ruby/day_18.rb
@@ -0,0 +1,39 @@
+falling_bytes = DATA.read.scan(/\d+/).map(&:to_i).each_slice(2).to_a
+
+corrupted = falling_bytes[0,1024]
+
+max = 70
+
+deltas = [[-1,0], [1,0], [0,-1], [0,1]]
+
+start = [0,0]
+stop = [max,max]
+
+scores = Hash.new(Float::INFINITY)
+scores[start] = 0
+frontier = [start]
+visited = Set.new
+until scores.has_key?(stop)
+ current = frontier.shift
+ visited << current
+
+ neighbors = deltas.map {|delta|
+ current.zip(delta).map { _1 + _2 }
+ }.select {|xy|
+ xy.all? { (0..max).cover?(_1) }
+ }.reject {|xy|
+ corrupted.include?(xy) || visited.include?(xy)
+ }
+ neighbors.each do |xy|
+ scores[xy] = [scores[xy], scores.fetch(current) + 1].min
+ end
+
+ frontier.concat(neighbors)
+
+ frontier.uniq!
+ frontier.sort_by! { scores.fetch(_1) }
+end
+
+pp scores.fetch(stop)
+
+__END__