yを長さnのベクトル(例:0 1 2...(n-1))とすると要素の順列の数はnの階乗です(! n)。ユーティリティ動詞tapを次のように定義すると、tap nですべての順列が列挙されます。
tap=: i. @ ! A. i. NB.=>((i.@!) A. i.)というフォーク。従ってtap 3 => (i.@!)3 A. i.3 => 0 1 2 3 4 5 A. 0 1 2となる tap 3 0 1 2 0 2 1 1 0 2 1 2 0 2 0 1 2 1 0
この順列は順序よく並んでいます。従って、要素nの順列はこの表(tap n)上の順序(インデックス)で一意に定まります。このインデックスは順列のアトム表示と呼ばれます。単項動詞としてA.(ラージエイドット)を用いると順列のアトム表示を算出します。たとえば要素数3からなる順列で2 1 0とすると、A.2 1 0は表(tap 3)上のインデックスを返します。(つまり5ということ)
A. 2 1 0 5 5 { tap 3 2 1 0 A.2 { tap 3 2 2 { tap 3 1 0 2 A.1 0 2 2
A.(ラージエイドット)を二項動詞として使うとアトム表示の結果を配列に適用します。
2 1 0 { 'PQR' RQP 5 A. 'PQR' RQP (i.6) A. 'PQR' PQR PRQ QPR QRP RPQ RQP
このようになんであれ配列のすべての順列を列挙することができます。ある単語のアナグラムを算出するなどです。
応用として、そのような計算に多大な時間がかかる場合、たとえば一度に100ずつやりたい場合があったとします。引数にボックスで計算対象のベクトル、スタート(アトムインデックス)、一度に算出したい数、という3つの要素を入れます。
LPerms =: 3 : 0 'arg start count' =. y (start + i. count) A. " 0 1 arg ) LPerms 'abcde'; 0; 4 abcde abced abdce abdec LPerms 'abcde'; 4; 4 abecd abedc acbde acbed
注:ここで勉強になるのがボックス化した引数のプログラム中での処理です。右側のボックス全体をyとして、yからargとstartとcountという3つの変数を一度にセットしています。