「継子立て」を Squeak Smalltalk で


無限リストは使わず、破壊的に、どちらかというと物語の様子をシミュレートする気分で書いてみました。

| children removeAt removees fifteenth |
children := (1 to: 30) asOrderedCollection.
removeAt :=[:n | 
   | allToRemovee |
   allToRemovee := children removeFirst: (children indexOf: (children atWrap: n)).
   children addAll: allToRemovee; removeLast].
removees := OrderedCollection new.
15 timesRepeat: [removees add: (removeAt value: 10)].
fifteenth := children addFirst: removees last.
15 timesRepeat: [removeAt value: 10].

^{fifteenth. children asSortedArray. removees asSortedArray}
"=> #(14 #(14) #(3 7 8 9 10 11 14 15 20 22 23 24 26 27 30)) "


ワークスペースなどに貼り付けて評価(print it。alt/cmd + p)できます。評価すると、機転を利かせた15番目に除かれそうになった子の位置、最後に残った子の位置、15人の(15番目に除かれそうになった子を含む)除かれた子たちの位置 を配列で返してきます。


children は子たちに見立てた 1〜30 までの数。
removeAt は指定した順番の子を除いて、その次の子を先頭に children を並び直させる関数で、除かれた子を返します。

並び直させるには、n 番目の子の番号をまず atWrap: n で特定(人数が n より少なくても機能させるため)、その子が先頭から何番目の子なのかをあらためて #indexOf: で調べてから、その子までをいったん #removeFirst: で chldren から除いてそのまま children の最後に #addAll: で付け足します。最後に children から最後の子を removeLast して返値としてます。


あとは実際に子を除いていく作業です。

15回、removeAt value: 10 を(除いた子を removees に追加しつつ)繰り返したところで、機転を利かせた 15番目の子を fifteenth にひかえておきつつ children の先頭にもどしてやります。これが物語のクライマックスですね。

再び 15回繰り返した後、残った子がめでたく fifteeth の子だったというお話でした。



追記: removeAt の処理に Transcript showln: children asArray. などと加えた後、トランスクリプトを開いて評価すると、14 の位置にいた 15番目に除かれそうになった子が生き残っていく様子も見て取れます。

#(1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30)
#(11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 1 2 3 4 5 6 7 8 9)
#(21 22 23 24 25 26 27 28 29 30 1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19)
#(1 2 3 4 5 6 7 8 9 11 12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 28 29)
#(12 13 14 15 16 17 18 19 21 22 23 24 25 26 27 28 29 1 2 3 4 5 6 7 8 9)
#(23 24 25 26 27 28 29 1 2 3 4 5 6 7 8 9 12 13 14 15 16 17 18 19 21)
#(4 5 6 7 8 9 12 13 14 15 16 17 18 19 21 23 24 25 26 27 28 29 1 2)
#(16 17 18 19 21 23 24 25 26 27 28 29 1 2 4 5 6 7 8 9 12 13 14)
#(28 29 1 2 4 5 6 7 8 9 12 13 14 16 17 18 19 21 23 24 25 26)
#(12 13 14 16 17 18 19 21 23 24 25 26 28 29 1 2 4 5 6 7 8)
#(25 26 28 29 1 2 4 5 6 7 8 12 13 14 16 17 18 19 21 23)
#(8 12 13 14 16 17 18 19 21 23 25 26 28 29 1 2 4 5 6)
#(25 26 28 29 1 2 4 5 6 8 12 13 14 16 17 18 19 21)
#(12 13 14 16 17 18 19 21 25 26 28 29 1 2 4 5 6)
#(28 29 1 2 4 5 6 12 13 14 16 17 18 19 21 25)
#(14 16 17 18 19 21 25 28 29 1 2 4 5 6 12 13)
#(2 4 5 6 12 13 14 16 17 18 19 21 25 28 29)
#(19 21 25 28 29 2 4 5 6 12 13 14 16 17)
#(13 14 16 17 19 21 25 28 29 2 4 5 6)
#(4 5 6 13 14 16 17 19 21 25 28 29)
#(28 29 4 5 6 13 14 16 17 19 21)
#(21 28 29 4 5 6 13 14 16 17)
#(21 28 29 4 5 6 13 14 16)
#(28 29 4 5 6 13 14 16)
#(4 5 6 13 14 16 28)
#(13 14 16 28 4 5)
#(4 5 13 14 16)
#(4 5 13 14)
#(13 14 4)
#(14 4)