[2022][ruby][14.x] refactored
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