[2018][ruby][17.1] settling and overflow
change yxoqutllzqwwounvtloqtnmkzvslzyns
commit 83e9ffe5ddb1ae34b2babc65b1d889aa647cb999
author Alpha Chen <alpha.chen@gmail.com>
date
parent onrnnnxy
diff --git a/2018/ruby/day_17.rb b/2018/ruby/day_17.rb
index 3c2ff1b..68fec69 100644
--- a/2018/ruby/day_17.rb
+++ b/2018/ruby/day_17.rb
@@ -24,16 +24,48 @@ class Slice
   def simulate
     return enum_for(__method__) unless block_given?
 
+    max_y = @squares.keys.map(&:last).max
+
     loop do
-      @active.to_a.each do |x, y|
-        @active.delete([x, y])
-        case @squares.fetch([x, y])
+      settled = []
+      @active.to_a.each do |pos|
+        @active.delete(pos)
+        x, y = pos
+        case @squares.fetch(pos)
         when ?+
           @squares[[x, y+1]] = ?|
           @active << [x, y+1]
         when ?|
-          @squares[[x, y+1]] = ?|
-          @active << [x, y+1]
+          if @squares[[x, y+1]].nil?
+            if y+1 <= max_y
+              @squares[[x, y+1]] = ?|
+              @active << [x, y+1]
+            end
+          else
+            left = @squares[[x-1, y]].nil?
+            right = @squares[[x+1, y]].nil?
+            if !left && !right
+              settled << [x, y]
+            end
+            if left
+              @squares[[x-1, y]] = ?|
+              @active << [x-1, y]
+            end
+            if right
+              @squares[[x+1, y]] = ?|
+              @active << [x+1, y]
+            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
 
@@ -89,7 +121,6 @@ class TestSlice < Minitest::Test
     simulation = @slice.simulate
 
     slice = 5.times { simulation.next }
-
     assert_equal <<~SLICE.chomp, @slice.to_s
       ......+.......
       ......|.....#.
@@ -106,6 +137,96 @@ class TestSlice < Minitest::Test
       ....#.....#...
       ....#######...
     SLICE
+
+    slice = 6.times { simulation.next }
+    assert_equal <<~SLICE.chomp, @slice.to_s
+      ......+.......
+      ......|.....#.
+      .#..#.|.....#.
+      .#..#.|#......
+      .#..#.|#......
+      .#....|#......
+      .#~~~~~#......
+      .#######......
+      ..............
+      ..............
+      ....#.....#...
+      ....#.....#...
+      ....#.....#...
+      ....#######...
+    SLICE
+
+    slice = 5.times { simulation.next }
+    assert_equal <<~SLICE.chomp, @slice.to_s
+      ......+.......
+      ......|.....#.
+      .#..#.|.....#.
+      .#..#.|#......
+      .#..#.|#......
+      .#~~~~~#......
+      .#~~~~~#......
+      .#######......
+      ..............
+      ..............
+      ....#.....#...
+      ....#.....#...
+      ....#.....#...
+      ....#######...
+    SLICE
+
+    slice = 4.times { simulation.next }
+    assert_equal <<~SLICE.chomp, @slice.to_s
+      ......+.......
+      ......|.....#.
+      .#..#.|.....#.
+      .#..#~~#......
+      .#..#~~#......
+      .#~~~~~#......
+      .#~~~~~#......
+      .#######......
+      ..............
+      ..............
+      ....#.....#...
+      ....#.....#...
+      ....#.....#...
+      ....#######...
+    SLICE
+
+    slice = 24.times { simulation.next }
+    assert_equal <<~SLICE.chomp, @slice.to_s
+      ......+.......
+      ......|.....#.
+      .#..#||||...#.
+      .#..#~~#|.....
+      .#..#~~#|.....
+      .#~~~~~#|.....
+      .#~~~~~#|.....
+      .#######|.....
+      ........|.....
+      ........|.....
+      ....#~~~~~#...
+      ....#~~~~~#...
+      ....#~~~~~#...
+      ....#######...
+    SLICE
+
+    slice = 9.times { simulation.next }
+    assert_equal <<~SLICE.chomp, @slice.to_s
+      ......+.......
+      ......|.....#.
+      .#..#||||...#.
+      .#..#~~#|.....
+      .#..#~~#|.....
+      .#~~~~~#|.....
+      .#~~~~~#|.....
+      .#######|.....
+      ........|.....
+      ...|||||||||..
+      ...|#~~~~~#|..
+      ...|#~~~~~#|..
+      ...|#~~~~~#|..
+      ...|#######|..
+    SLICE
   end
 end