Advertisement
musifter

AoC 2021 day 20 (smalltalk)

Dec 20th, 2021
2,642
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/local/bin/gst -q
  2.  
  3. Object subclass: TableAutomaton [
  4.     | rules cells buffer bidx live bounds border |
  5.  
  6.     max_iter := 50.     " NOTE: not checked for, but will throw out-of-bounds if you do "
  7.  
  8.     hdirs := Dictionary from: { 6 -> (1 @ -1). 3 -> (1 @ 0). 0 -> (1 @ 1) }.
  9.  
  10.     TableAutomaton class >> new: strArray rules: aTable [
  11.         ^(super new) init: strArray rules: aTable
  12.     ]
  13.  
  14.     init: strArray rules: aTable [
  15.         | x_size y_size |
  16.         rules  := aTable.
  17.         live   := 0.
  18.         border := 0.
  19.  
  20.         " Center bounds in the middle of a large array of arrays "
  21.         y_size := strArray size.
  22.         x_size := (strArray at: 1) size.
  23.  
  24.         bounds := Rectangle origin: (2 + max_iter) @ (2 + max_iter)
  25.                             corner: (x_size + max_iter + 1) @ (y_size + max_iter + 1).
  26.  
  27.         " Allocating two buffers to swap between iterations "
  28.         bidx   := 1.
  29.         buffer := (1 to: 2) collect: [ :buff |
  30.                       (1 to: (max_iter * 2 + y_size + 2)) collect: [:y |
  31.                           Array new: (max_iter * 2 + x_size + 2)
  32.                       ].
  33.                   ].
  34.  
  35.         " Cells points at the active buffer "
  36.         cells := buffer at: bidx.
  37.  
  38.         " Load data into active buffer "
  39.         strArray keysAndValuesDo: [ :y :line |
  40.             line keysAndValuesDo: [ :x :chr |
  41.                 live := live + ((cells at: (max_iter + y + 1)) at: (max_iter + x + 1)
  42.                                     put: (chr = $#) asCBooleanValue).
  43.  
  44.                 bounds right:  (bounds right  max: x).
  45.                 bounds bottom: (bounds bottom max: x).
  46.             ]
  47.         ].
  48.         ^self
  49.     ]
  50.  
  51.     runTurn [
  52.         | next idx |
  53.         next := buffer at: (bidx := 3 - bidx).
  54.         live := 0.
  55.  
  56.         bounds origin: (bounds origin - (1@1)) corner: (bounds corner + (1@1)).
  57.  
  58.         (bounds top to: bounds bottom) do: [ :y |
  59.             " idx into rules handled with bit twiddling to reduce repeated work "
  60.             idx := (border = 1) ifTrue: [16r1FF] ifFalse: [0].
  61.  
  62.             (bounds left to: bounds right) do: [ :x |
  63.                 idx := ((idx bitAnd: 16r0DB) bitShift: 1) bitAnd: 16r1FF.
  64.  
  65.                 hdirs keysAndValuesDo: [ :shift :dir |
  66.                    | bit |
  67.                     bit := (cells at: y + dir y) at: (x + dir x).
  68.                     bit ifNil: [ bit := border ].
  69.  
  70.                     idx := idx bitOr: (bit bitShift: shift).
  71.                 ].
  72.  
  73.                 live := live + ((next at: y) at: x put: (rules at: idx + 1)).
  74.             ]
  75.         ].
  76.  
  77.         border := rules at: (511 * border) + 1.
  78.         cells  := next.
  79.     ]
  80.  
  81.     live    [ ^live   ]
  82.     border  [ ^border ]
  83.  
  84.     printOn: aStream [
  85.         (bounds top to: bounds bottom) do: [ :y |
  86.             (bounds left to: bounds right) do: [ :x |
  87.                 aStream nextPut: ((((cells at: y) at: x) = 1) ifTrue: [$#] ifFalse: [$.]).
  88.             ].
  89.             aStream nl.
  90.         ].
  91.         aStream nextPutAll: ('Border: %1' % {border}); nl.
  92.     ]
  93. ]
  94.  
  95. "
  96. | Mainline
  97. "
  98. ObjectMemory spaceGrowRate: 500.0.
  99.  
  100. input := stdin lines contents.
  101. table := input first asArray collect: [:chr | (chr = $#) asCBooleanValue].
  102. auto  := TableAutomaton new: (input allButFirst: 2) rules: table.
  103.  
  104. (1 to: 50) do: [ :time |
  105.     auto runTurn.
  106.     ('Turn: %1  Live cells: %2%3  Time: %4' % {
  107.         time.
  108.         auto live.
  109.         (auto border = 0) ifTrue: ['  '] ifFalse: ['+∞'].
  110.         Time millisecondClock / 1000.0
  111.     }) displayNl.
  112.  
  113.     stdout flush.
  114.  
  115.     (time = 2) ifTrue: [ ('Part 1: %1' % {auto live}) displayNl. stdout flush ].
  116. ].
  117.  
  118. ('Part 2: %1' % {auto live}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement