Advertisement
musifter

AoC day 17, Smalltalk

Dec 17th, 2020
1,980
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #!/usr/local/bin/gst -q
  2.  
  3. "
  4. |  Part 1: set to 3
  5. |  Part 2: set to 4
  6. "
  7. num_dimensions := 3.
  8.  
  9. " Extension to numbers: convert to an array of digits in a specified radix. "
  10. Number extend [
  11.     asListRadix: n [
  12.         | ret x |
  13.         ret := OrderedCollection new.
  14.  
  15.         x := self.
  16.         [ (x >= n) ] whileTrue: [
  17.             ret addLast: (x \\ n).
  18.             x := x // n.
  19.         ].
  20.         ^ret addLast: x; yourself.
  21.     ]
  22. ]
  23.  
  24. " Extension for Array for simple vector addition "
  25. Array extend [
  26.     + arr [
  27.         | ret |
  28.         ret := Array new: (self size).
  29.         self doWithIndex: [ :n :i | ret at: i put: ((self at: i) + (arr at: i)) ].
  30.         ^ret
  31.     ]
  32. ]
  33.  
  34. "
  35. |  Class to maintain an N-space for our Conway Cubes.
  36. "
  37. Object subclass: NSpace [
  38.     | neigh dims space row active live |
  39.  
  40.     " Constructors: "
  41.     NSpace class >> new [
  42.         ^(super new) init: 3
  43.     ]
  44.  
  45.     NSpace class >> dims: d [
  46.         ^(super new) init: d
  47.     ]
  48.  
  49.     " Initialization: "
  50.     init: d [
  51.         | num_neigh |
  52.         dims := d.
  53.         live := 0.
  54.         row  := 1.      " Only used for loading "
  55.  
  56.         space := LookupTable new.
  57.         active := Set new.
  58.  
  59.         " Build table of vectors for neighbours "
  60.         num_neigh := ((3 raisedTo: dims) - 1).
  61.         neigh := Array new: num_neigh.
  62.         (1 to: num_neigh) do: [ :i |
  63.            | list |
  64.             list := (i asListRadix: 3).
  65.             [ list size < dims ] whileTrue: [
  66.                 list addLast: 0.
  67.             ].
  68.  
  69.             neigh at: i put: (list collect: [ :n | (n = 2) ifTrue: [-1] ifFalse: [n] ]) asArray.
  70.         ].
  71.  
  72.         ^self
  73.     ]
  74.  
  75.     " Load Space from strings "
  76.     loadRow: str [
  77.         str doWithIndex: [:c :i |
  78.            | coord |
  79.             coord := Array new: dims withAll: 0.
  80.             coord at: 1 put: i; at: 2 put: row.
  81.             (c == $#) ifTrue: [ self setLive: coord ].
  82.         ].
  83.         row := row + 1.
  84.     ]
  85.  
  86.     " Accessors: "
  87.     getActive  [ ^active ]      " Set of cells that might change "
  88.     getNumLive [ ^live ]        " Number of live cells "
  89.  
  90.     getCell: coord [
  91.         ^space at: (coord printString) ifAbsent: [0]
  92.     ]
  93.  
  94.     " Set a cell to live, mark neighbours for checking next time "
  95.     setLive: coord [
  96.         space at: (coord printString) put: 1.
  97.         self markNeighbours: coord.
  98.         live := live + 1.
  99.     ]
  100.  
  101.     " Number of live cells adjacent to coord "
  102.     countNeighbours: coord [
  103.         ^neigh inject: 0 into: [ :acc :vec | acc + (self getCell: (coord + vec)) ]
  104.     ]
  105.  
  106.     " Add coord and its neighbours to the Set to check next time "
  107.     markNeighbours: coord [
  108.         active add: coord.
  109.         neigh do: [ :vec | active add: (coord + vec) ].
  110.     ]
  111. ]
  112.  
  113. "
  114. |  Mainline:
  115. "
  116. " Load initial state: "
  117. curr := NSpace dims: num_dimensions.
  118. stdin linesDo: [ :line |
  119.     curr loadRow: line.
  120. ].
  121.  
  122. " Run cellular automata: "
  123. (1 to: 6) do: [ :t |
  124.     next := NSpace dims: num_dimensions.
  125.     (curr getActive) do: [ :coord |
  126.        | neigh |
  127.         neigh := curr countNeighbours: coord.
  128.  
  129.         ((curr getCell: coord) = 1) ifTrue: [
  130.             ((neigh = 2) or: [ neigh = 3 ]) ifTrue: [ next setLive: coord ].
  131.         ] ifFalse: [
  132.             (neigh = 3) ifTrue: [ next setLive: coord ].
  133.         ].
  134.     ].
  135.  
  136.     stdout nextPutAll: ('Time: ', t asString, '; Live: ', next getNumLive asString); nl; flush.
  137.     curr := next.
  138. ]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement