[2018][ruby][17.1] fix simulation
change qzysztsslmznxklzwslqptksqspxptsm
commit bee771a7284b0b5724a80216153659392f974998
author Alpha Chen <alpha.chen@gmail.com>
date
parent zmumwows
diff --git a/2018/ruby/day_17.rb b/2018/ruby/day_17.rb
index 48235bf..41d1169 100644
--- a/2018/ruby/day_17.rb
+++ b/2018/ruby/day_17.rb
@@ -15,6 +15,8 @@ class Slice
     new(squares)
   end
 
+  attr_reader :squares
+
   def initialize(squares)
     @squares = squares
     @squares[[500, 0]] = ?+
@@ -27,7 +29,6 @@ class Slice
     max_y = @squares.keys.map(&:last).max
 
     loop do
-      settled = []
       @active.to_a.each do |pos|
         @active.delete(pos)
         x, y = pos
@@ -36,38 +37,37 @@ class Slice
           @squares[[x, y+1]] = ?|
           @active << [x, y+1]
         when ?|
+          next if y+1 > max_y
+
           if @squares[[x, y+1]].nil?
-            if y+1 <= max_y
-              @squares[[x, y+1]] = ?|
-              @active << [x, y+1]
-            end
+            @squares[[x, y+1]] = ?|
+            @active << [x, y+1]
           else
-            left = @squares[[x-1, y]].nil?
-            right = @squares[[x+1, y]].nil?
-            if !left && !right
-              settled << [x, y]
-            end
-            if left
+            if @squares[[x-1, y]].nil?
               @squares[[x-1, y]] = ?|
               @active << [x-1, y]
             end
-            if right
+
+            if @squares[[x+1, y]].nil?
               @squares[[x+1, y]] = ?|
               @active << [x+1, y]
             end
+
+            left_x = x-1
+            left_x -= 1 until @squares[[left_x, y]] != ?|
+            right_x = x+1
+            right_x += 1 until @squares[[right_x, y]] != ?|
+            if @squares[[left_x, y]] == ?# && @squares[[right_x, y]] == ?#
+              (left_x+1..right_x-1).each do |x|
+                @squares[[x, y]] = ?~
+                @active << [x, y-1] if @squares[[x, y-1]] == ?|
+              end
+            end
           end
         end
       end
 
-      if @active.empty?
-        while pos = settled.shift
-          @squares[pos] = ?~ if @squares[pos] == ?|
-          x, y = pos
-          @active << [x, y-1] if @squares[[x, y-1]] == ?|
-          settled << [x-1, y] if @squares[[x-1, y]] == ?|
-          settled << [x+1, y] if @squares[[x+1, y]] == ?|
-        end
-      end
+      return if @active.empty?
 
       yield self
     end
@@ -139,7 +139,7 @@ class TestSlice < Minitest::Test
       ....#######...
     SLICE
 
-    6.times { simulation.next }
+    5.times { simulation.next }
     assert_equal <<~SLICE.chomp, @slice.to_s
       ......+.......
       ......|.....#.
@@ -157,7 +157,7 @@ class TestSlice < Minitest::Test
       ....#######...
     SLICE
 
-    5.times { simulation.next }
+    4.times { simulation.next }
     assert_equal <<~SLICE.chomp, @slice.to_s
       ......+.......
       ......|.....#.
@@ -175,7 +175,7 @@ class TestSlice < Minitest::Test
       ....#######...
     SLICE
 
-    4.times { simulation.next }
+    2.times { simulation.next }
     assert_equal <<~SLICE.chomp, @slice.to_s
       ......+.......
       ......|.....#.
@@ -193,7 +193,7 @@ class TestSlice < Minitest::Test
       ....#######...
     SLICE
 
-    24.times { simulation.next }
+    21.times { simulation.next }
     assert_equal <<~SLICE.chomp, @slice.to_s
       ......+.......
       ......|.....#.
@@ -234,6 +234,21 @@ class TestSlice < Minitest::Test
 end
 
 def solve(input)
+  slice = Slice.parse(input)
+  min_y = slice.squares.select {|_,s| s == ?# }.map(&:first).map(&:last).min
+  simulation = slice.simulate
+
+  loop do
+    simulation.next
+  end
+
+  # puts
+  # min_x, max_x = slice.water.map(&:first).minmax
+  # min_y, max_y = slice.water.map(&:last).minmax
+  # min_y = [0, min_y].min
+  # puts (min_y..max_y).map {|y| (min_x-1..max_x+1).map {|x| slice.squares.fetch([x, y]) { ?. } }.join }.join(?\n)
+
+  slice.water.count {|_,y| y >= min_y }
 end
 
 if __FILE__ == $0