[2022][ruby][14.x] refactored
change xnttkkslrzxyyzvswyrrzzszvzpwpqtv
commit 52b20142a3e5ff68911352ef2b7b7297b35b0da6
author Alpha Chen <alpha@kejadlen.dev>
date
parent ksyyukxs
diff --git a/2022/ruby/day_14.rb b/2022/ruby/day_14.rb
index 55d3c87..23bb08f 100644
--- a/2022/ruby/day_14.rb
+++ b/2022/ruby/day_14.rb
@@ -12,51 +12,41 @@ cave = scan.each.with_object({}) {|line, cave|
     }
 }
 
-x_min, x_max = cave.keys.map(&:first).minmax
-y_min, y_max = cave.keys.map(&:last).minmax
+def cave.to_s
+  x_min, x_max = keys.map(&:first).minmax
+  y_min, y_max = keys.map(&:last).minmax
 
-inspect_cave = -> {
-  puts (0..y_max+1).map {|y|
+  (0..y_max+1).map {|y|
     (x_min-1..x_max+1).map {|x|
-      cave[[x, y]] || ?.
+      self.fetch([x, y], ?.)
     }.join
   }.join("\n")
-}
-
-# part one
-# sands = 0
-# loop do
-#   inspect_cave.()
-#   sands += 1
+end
 
-#   pos = [500, 0]
-#   while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
-#     pos = next_pos
-#     break if pos[1] >= y_max
-#   end
-#   break if pos[1] >= y_max
+def pour_sand(cave, stop:)
+  return enum_for(__method__, cave, stop:) unless block_given?
 
-#   cave[pos] = ?o
-# end
+  loop do
+    # puts cave
+    pos = [500, 0]
 
-# inspect_cave.()
-# p sands-1
+    while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
+      pos = next_pos
+      break if stop.(*pos)
+    end
+    break if stop.(*pos)
 
-# part two
-cave.default_proc = ->(h,(x,y)) { h[[x, y]] = y == y_max + 2 ? ?# : nil }
-sands = 0
-loop do
-  # inspect_cave.()
-  sands += 1
-
-  pos = [500, 0]
-  while next_pos = [0, -1, 1].map {|dx| pos.zip([dx, 1]).map { _1 + _2 }}.find { cave[_1].nil? }
-    pos = next_pos
+    cave[pos] = ?o
+    yield pos
   end
-  break if pos == [500, 0]
-
-  cave[pos] = ?o
 end
 
-inspect_cave.()
-p sands
+y_max = cave.keys.map(&:last).max
+
+# part one
+p pour_sand(cave, stop: ->(_, y) { y >= y_max }).count
+
+# part two
+cave.delete_if { _2 == ?o } # reset cave
+cave.default_proc = ->(_,(_,y)) { y == y_max + 2 ? ?# : nil }
+p pour_sand(cave, stop: ->(x, y) { [x, y] == [500, 0] }).count + 1