さすがにもう縮まないのでネタバレ
最終的に1525バイトになった。劇的に縮められる新機軸はもうなさそうなのでネタバレ
データは以下のようにひとつの関数にエンコードする。すなわち「w → Ww」「W→WWw」「v→WWWw」になる。
let.dat = abs o1 do let.o2 = o1(o1) # w let.o3 = o1(o2) # W let.o4 = o1(o3) # v let.o5 = o4(o4) # w let.o6 = o4(o5) # W let.o7 = o4(o6) # v end
スタックの少し前にある関数にスタックのトップを適用すると、スタック位置の差によって「wWv」のいずれかが出力される。
よって、oN は次のように動作しないといけない。
o3(o3) -> (out w); o4 | (out Ww); o4 o2(o3) -> (out W); o4 | (out WWw); o4 o1(o3) -> (out v); o4 | (out WWWw); o4
エンコード前のデータを出力するときは左の結果、エンコード後のデータなら右。
ふたつの動作はほとんど同じなので、各々トリプルを作ってdatをスキャンする関数に渡せばよい
ラムダ計算ではトリプルはこうやって作る。
let.triplet = abs a, b, c, f do f(a, b, c) end let.tr1 = triplet(out_w, out_W, out_v) let.tr2 = triplet(out_Ww, out_WWw, out_WWWw) scan_dat(tr1) # エンコード前のデータが出力される scan_dat(tr2) # エンコード後のデータが出力される
あとはscan_datをどう作るかである。
oNはoMを受け取ったら、(M-N)%3を計算して、o(M+1)を返さないといけないので、
とりあえずは
let.oN = abs my, tr, n, oM do ... (exec_tr tr (m_n_mod3 (get_m oM) n))) ... (my my tr (succ (get_m oM))) end
こういう感じになると思う。
ここで、問題になるのは
o3 == (oN oN tr 3) o2 == (oN oN tr 2)
という感じに、oNとoMの中身は同じ関数なので、oMからMをとってくる機能もこの関数の中にいれないといけないのである。
これが今回一番難しいところだ。