Ulam Spiral を Squeak Smalltalk で
ちょうど無限素数列を使えそうなお話だったので Squeak Smalltalk で描いてみました。日本語版Squeak(Squeak4.2-ja-all-in-one) などのワークスペースへペースト後、あらためて選択してから do it(式を評価、alt/cmd + d など)で下の図が得られます。
| primesGen pen dotSize width center isPrimeOrNotGen form | primesGen := Generator on: [:g | | primes next | primes := OrderedCollection withAll: #(2 3 5 7). primes do: [:prime | g value: (next := prime)]. [ [:exit | [ next := next + 2. primes anySatisfy: [:prime | prime * prime > next ifTrue: [exit value]. next isDivisibleBy: prime] ] whileTrue] valueWithExit. g value: (primes add: next) ] repeat]. isPrimeOrNotGen := Generator on: [:g | 1 to: Float infinity do: [:n | primesGen peek = n ifTrue: [primesGen next. g value: true] ifFalse: [g value: false]]]. dotSize := 2. width := 200. center := Display center. pen := Pen new defaultNib: dotSize. pen place: center. pen north; turn: 180. Display fillWhite; restoreAfter: [ 1 to: width do: [:length | 2 timesRepeat: [ pen turn: -90. length timesRepeat: [ isPrimeOrNotGen next ifTrue: [pen down]. pen go: 0; up; go: dotSize]]]. form := Form fromDisplay: (center - (width * dotSize// 2) extent: width asPoint * dotSize + dotSize)]. form asMorph openInHand
もっとも、今回のように矩形のサイズをあらかじめ決めてしまうのであれば、必要な素数の最大値も決まるので、組み込みの素数生成器(Integer class>>#primesUpTo:)でもまったく問題ありません。
| pen dotSize width center isPrimeOrNotGen form | width := 200. isPrimeOrNotGen := Generator on: [:g | | primesStream | primesStream := (Integer primesUpTo: width * (width + 1) + 1) readStream. 1 to: Float infinity do: [:n | primesStream peek = n ifTrue: [primesStream next. g value: true] ifFalse: [g value: false]]]. dotSize := 2. center := Display center. pen := Pen new defaultNib: dotSize. pen place: center. pen north; turn: 180. Display fillWhite; restoreAfter: [ 1 to: width do: [:length | 2 timesRepeat: [ pen turn: -90. length timesRepeat: [ isPrimeOrNotGen next ifTrue: [pen down]. pen go: 0; up; go: dotSize]]]. form := Form fromDisplay: (center - (width * dotSize// 2) extent: width asPoint * dotSize + dotSize)]. form asMorph openInHand