いきなりですが次のコードを見てみましょう.
a(X):XXXXrXXXXra(sX) a(r)
このコードとほぼ同様の経路を実現する方法として, 多変数による繰り返しの講では,
次のような書き方を紹介したかと思います.
a(X,Y):YYa(sX,XXXXr) a(r,)
今回はやはり同様の経路を,また違った方法で実現してみましょう.
a(X,Y):XXXXra(sY,X) a(r,r)
動かしてみると, 上のコードと同byte数で, (少し変わりますが)同様の経路を描くことが分かると思います.
仕組みを説明しましょう.再帰の[X,Y]の部分がどのように成長していくのか,
その結果Xとしては何が出てくるのかを書きだしてみます:
[r,r], [sr,r], [sr,sr], [ssr,sr], …
X:r, sr, sr, ssr, ssr, sssr, …
Xが2回に1回成長しながら大きくなっていくのが分かると思います.
これが今回説明する「成長速度の調整」の特別な場合です.
今回は「1/2倍速で育てる」ことである種2倍関数を省略するような目的で使用できました.
他にも例えば
a(A,X,Y):……a(srslA,sY,X) a(,,)
などとすると, srslがN段階成長する(A)間にsは大体N/2回成長します(XとY).
このようにいくつかのパターンに速度の緩急をつけて成長させることが出来るのです.
なお,N/2倍のsと同時にN倍のsを利用したいときは, 単に2倍して「XX」などとすると少しズレてしまいますが,
「XY」とするとこれがちょうど「1段階にsずつ成長」してくれています.
他の例を見てみましょう:
a(X,Y,Z):Xra(ssY,sZ,X) a(,,)
sの個数で見て
0,2,3,3,5,6,6,8,9,…
となるのが分かると思います. 規則が分かりにくかったら3つずつで区切って
[0,2,3][3,5,6][6,8,9]
と考えてください. 「同じパターンが3増えて再帰」と思って1変数で
a(X):XssXsssXa(sssX) a(r)
なんて書くよりもよっぽど短く書けていることにも注目すべきでしょう.
仕組みが理解できたら,
[0,1,3][3,4,6][6,7,9][9,10,12]…
[0,4,2][2,6,4][4,8,6]…
[0,2,1][1,3,2][2,4,3]…
なども(なるべく少ないbyte数で)作ってみてください. 一応正解を一番下に用意しておきます.
以上具体例を見てきましたが,「成長速度の調整」としては次が基本形になります:
a(X,Y,Z):[Xを含む何か]a(uY,vZ,wX)
もちろん変数は2つでも4つ以上でも同様です.
上記の場合3回で合計uvw成長する規則となっています.
大体の場合はこの
●回で合計■成長する
というところから始めてそれを振り分けると実装しやすいのではないかと思います.
なお, 具体例としては「sを増やしていく」というタイプの育てばかりを扱いましたが,
もちろんs以外をつけることもあります. 例えば「2回で合計srsl成長している」となれば
a(X,Y):……a(sY,rslX)
などのコードを考えてみると上手く行くかもしれません.
さて, 上記で問題を出したの解答を示しておきましょう.
a(X,Y,Z):Xra(sY,ssZ,X) a(,,)
a(X,Y,Z):Xra(ssY,Z,X) a(,ss,)
a(X,Y,Z):X a(sY,Z,X) a(,s,)
第2の例では「3回やって合計2成長する」なので, 1周期目から4を作るには
初期値で2与える必要がありますね. 第3の例も同様です.