Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/local/bin/gst -q
- Object subclass: TableAutomaton [
- | rules cells buffer bidx live bounds border |
- max_iter := 50. " NOTE: not checked for, but will throw out-of-bounds if you do "
- hdirs := Dictionary from: { 6 -> (1 @ -1). 3 -> (1 @ 0). 0 -> (1 @ 1) }.
- TableAutomaton class >> new: strArray rules: aTable [
- ^(super new) init: strArray rules: aTable
- ]
- init: strArray rules: aTable [
- | x_size y_size |
- rules := aTable.
- live := 0.
- border := 0.
- " Center bounds in the middle of a large array of arrays "
- y_size := strArray size.
- x_size := (strArray at: 1) size.
- bounds := Rectangle origin: (2 + max_iter) @ (2 + max_iter)
- corner: (x_size + max_iter + 1) @ (y_size + max_iter + 1).
- " Allocating two buffers to swap between iterations "
- bidx := 1.
- buffer := (1 to: 2) collect: [ :buff |
- (1 to: (max_iter * 2 + y_size + 2)) collect: [:y |
- Array new: (max_iter * 2 + x_size + 2)
- ].
- ].
- " Cells points at the active buffer "
- cells := buffer at: bidx.
- " Load data into active buffer "
- strArray keysAndValuesDo: [ :y :line |
- line keysAndValuesDo: [ :x :chr |
- live := live + ((cells at: (max_iter + y + 1)) at: (max_iter + x + 1)
- put: (chr = $#) asCBooleanValue).
- bounds right: (bounds right max: x).
- bounds bottom: (bounds bottom max: x).
- ]
- ].
- ^self
- ]
- runTurn [
- | next idx |
- next := buffer at: (bidx := 3 - bidx).
- live := 0.
- bounds origin: (bounds origin - (1@1)) corner: (bounds corner + (1@1)).
- (bounds top to: bounds bottom) do: [ :y |
- " idx into rules handled with bit twiddling to reduce repeated work "
- idx := (border = 1) ifTrue: [16r1FF] ifFalse: [0].
- (bounds left to: bounds right) do: [ :x |
- idx := ((idx bitAnd: 16r0DB) bitShift: 1) bitAnd: 16r1FF.
- hdirs keysAndValuesDo: [ :shift :dir |
- | bit |
- bit := (cells at: y + dir y) at: (x + dir x).
- bit ifNil: [ bit := border ].
- idx := idx bitOr: (bit bitShift: shift).
- ].
- live := live + ((next at: y) at: x put: (rules at: idx + 1)).
- ]
- ].
- border := rules at: (511 * border) + 1.
- cells := next.
- ]
- live [ ^live ]
- border [ ^border ]
- printOn: aStream [
- (bounds top to: bounds bottom) do: [ :y |
- (bounds left to: bounds right) do: [ :x |
- aStream nextPut: ((((cells at: y) at: x) = 1) ifTrue: [$#] ifFalse: [$.]).
- ].
- aStream nl.
- ].
- aStream nextPutAll: ('Border: %1' % {border}); nl.
- ]
- ]
- "
- | Mainline
- "
- ObjectMemory spaceGrowRate: 500.0.
- input := stdin lines contents.
- table := input first asArray collect: [:chr | (chr = $#) asCBooleanValue].
- auto := TableAutomaton new: (input allButFirst: 2) rules: table.
- (1 to: 50) do: [ :time |
- auto runTurn.
- ('Turn: %1 Live cells: %2%3 Time: %4' % {
- time.
- auto live.
- (auto border = 0) ifTrue: [' '] ifFalse: ['+∞'].
- Time millisecondClock / 1000.0
- }) displayNl.
- stdout flush.
- (time = 2) ifTrue: [ ('Part 1: %1' % {auto live}) displayNl. stdout flush ].
- ].
- ('Part 2: %1' % {auto live}) displayNl.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement