順列

異なるn個のものを並べます。その並べ方を全部書き出すプログラムを作ってみましょう。

まず,具体的に考えます。

a,b,c の3文字を並べ替えると

[a,b,c],[a,c,b],[b,a,c],[b,c,a],[c,a,b],[c,b,a]

の6通りができます。

a,b,c,dの4文字を並べ替えたときはどうでしょう。

このとき,初めから考え直すのではなく,上の3文字の順列を利用することを考えるのです。

[a,b,c] の並びの両端と文字間の4箇所に d を入れていけば4通りの順列ができます。

他の並びについても同様にすれば,6×4=24通りの並びができますね。

これをプログラムします。

まず,[a,b,c] はリストとして処理できますので,このリストに1文字を追加する関数を作りましょう。

引数として,list と k,e を与えます。list の k番目に,要素 e を挿入するのです。

関数の中で新しいリスト(戻り値として使うので rt)を用意し,list の k-1 番目までをまずコピー(順に追加)します。

k番目に要素eを入れて,listのk番目からあとをさらに追加します。

=======================================

inslist(list,k,e):=(

  m=length(list);

  rt=[];

  repeat(k-1,s,rt=append(rt,list_s));

  rt=append(rt,e);

  repeat(m-k+1,s,rt=append(rt,list_(k+s-1)));

);

=======================================

戻り値は,最後に実行された rt=append(rt,list_(k+s-1))); のリストです。

次に,本体を作ります。perm(n)としましょう。

先ほど,3つの順列を利用して4つの順列を作りました。先ほどはa,b,cの文字でしたが文字だと追加する要素を決めにくいので,数字にします。

一般にn個の順列なら,n-1個の順列を利用することになります。

引数に n を与えて,まず n-1 個の順列を作るのです。

すると,順列を作る関数 perm(n) の中で perm(n-1)を実行することになります。

このような関数を「再帰的(リカージョン)」と言います。

さて,たとえば,n=4 にしたとき,perm(3) を実行しますが,その中では perm(2) を実行し,perm(2)の中では perm(1) を実行することになります。

どこかで止めないと無限に実行することになりますが,引数に0を与えるのは意味がないので,perm(1)で止めることにすればよいですね。

つまり,引数が n=1 のときはその結果:1つのものの順列:すなわち [[1]] を返すのです。リストのリストであることに注意してください。

すると,perm(2)では,[1]が返ってくるので,それに「2」を追加して[[1,2],[2,1]]ができます。

すると,perm(3)ではこれを利用して[[1,2,3],[3,1,2],[1,3,2],[2,1,3],[3,2,1],[2,3,1]] ができます。

最後に,これに 4 を追加したものができることになります。

=====================================

perm(n):=(

  if(n<2,ret=[[1]],

   ls=perm(n-1);

   ret=[];

   repeat(length(ls),s,

     ret=append(ret,append(ls_s,n));

     repeat(length(ls_s),t,

       ret=append(ret,inslist(ls_s,t,n));

     );

   );

  );

);

=====================================

 なお,リストの最初は,1,2,3,4 と順に並ぶものができるようにしています。

< 戻る >