これは再帰の打ち切りの項でも説明しました.
a(X,Y):XXXXa(sX,Y-1)などとして,a(r,10)などと使うというものです.
「不規則な色んなところを回収する」というたぐいの問題でも
場所によってはこのボムで一気に一部の領域を片づけることが出来ます.
また,「灰色マスは回収しはじめるまでは何度通ってもいい」というのも
ポイントで,正方形状の領域の一部が灰色でも,灰色マスの外側だけを先に
処理するという使い方ができます.一般的に初期位置から遠くは回収が
面倒なので,この考え方が役に立つ場面は結構あります.
経路が不規則になればなるほど,2倍,3倍関数などの利用場所は
限られてきます.関数は,Xをたくさん含むほど,(上手に使えたときの
利は大きくなりえますが)適用できる箇所が少なくなりやすいのです.
ここで紹介するのは,1変数関数でしかもXを1つしか含まないものの利用法です.
このような関数は,a(X):pXqの形だけです.
いきなりですが,次のコードを少ないbyte数に書き換えることを考えましょう:
abcpqabcuvabcpqwvupqwabcupqvabcpqabcpqabcabc【44byte】abcとpqがたくさんいるのが分かりますね.
[abc][pq][abc]uv[abc][pq]wvu[pq]w[abc]u[pq]v[abc][pq][abc][pq][abc][abc]実は上手な短縮をすると,このコードでClear出来る経路は,24byteで書くことができます.
さて,24byteになったでしょうか?
まずは素直な考え方を紹介しましょう.[abc]は3文字で8回,[pq]は2文字で6回現れる
ので,
これらは別の文字でおく方が短くなります:
x:abcだいぶ減りました.さらに[xy]が4回現れているので,これを再び
y:pq
xyxuvxywvuywxuyvxyxyxx【4+3+22=29byte】
x:abcさて,上のコードを見ても,これ以上減らせる箇所はなさそうです.
y:pq
z:xy zxuvzwvuywxuyvzzxx【4+3+3+18=28byte】
しかし,実はもっと良い方法があります.x:abc, y:pqと定義した代わりに
f(X):abcXpqという関数を定義しましょう:
「abc・・・・pq」がある度にf(・・・・)にすることで4byteの得が出来ます.
[pq]が出てくるたびに直前の[abc]とペアにすることで次の手順で
どんどんコードを短縮していくことができます.
一気にさきほどのコードのbyte数に追いつきました.[abc][pq][abc]uv[abc][pq]wvu[pq]w[abc]u[pq]v[abc][pq][abc][pq][abc][abc]【8+44=52byte, 関数+初期状態】 f()[abc]uv[abc][pq]wvu[pq]w[abc]u[pq]v[abc][pq][abc][pq][abc][abc]【52-4=48byte】 f()[abc]uvf()wvu[pq]w[abc]u[pq]v[abc][pq][abc][pq][abc][abc]【48-4=44byte】 f()f(uvf()wvu)w[abc]u[pq]v[abc][pq][abc][pq][abc][abc]【44-4=40byte】 f()f(uvf()wvu)wf(u)v[abc][pq][abc][pq][abc][abc]【40-4=36byte】 f()f(uvf()wvu)wf(u)vf()[abc][pq][abc][abc]【36-4=32byte】 f()f(uvf()wvu)wf(u)vf()f()[abc][abc]【32-4=28byte】
さて,随分と縮めた
f(X):abcXpqというコードですが,さらに短縮が可能です.素直な方法だと,
f()f(uvf()wvu)wf(u)vf()f()[abc][abc]【28byte】
x:abcよりよい方法は,「辿り終わった後に余分に実行しても構わない」
f(X):xXpq
f()f(uvf()wvu)wf(u)vf()f()xx【26byte】
予告通り,24byteに短縮することができました!f(X):abcXpq
f()f(uvf()wvu)wf(u)vf()f()[abc][abc][pq][pq]【28+4byte】f(X):abcXpq
f()f(uvf()wvu)wf(u)vf()f()[abc]f()[pq]【28byte】f(X):abcXpq
f()f(uvf()wvu)wf(u)vf()f()f(f())【24byte】
今回は「f(X):[abc]X[pq]」という関数による短縮を紹介しましたが,
これで全ての[abc][pq]が処理できるのは,「先頭から順に数えて,どの段階でも
[abc]が[pq]よりもたくさんある」という状況に限られます.
[pq]の方が少したくさんある場合などは,一部のpqについては
この関数とは別の方法(新たに文字でおくなど)で対処する必要があります.
なお,この「文字列を関数に置き換えて短縮していく」
という作業は結構大変です.しかも途中で1箇所間違えてカッコが1つ足りなかったり
しても,後から見つけるのが困難な場合が多いです.短縮を繰り返すほど
「見ても仕組みがよく分からないコード」が出来あがっていきます.
たくさんこの短縮を利用する場合は,こまめに実行してエラーが起きないか,
動きは想定通りかなどの検算をやりながら作業を進めるのが良いと思います.
今回のコードでは,いかにもたくさん反復されるもの[abc][pq]がありました.
そんな上手くいく状況はそうそうないと思うかもしれませんが,意外と適用例は多いです.
2例ほど紹介して終わることにしましょう.
ちなみにどちらも別に深い意味のある動きではないです.