エンジニアのソフトウェア的愛情

または私は如何にして心配するのを止めてプログラムを・愛する・ようになったか

右に回す、Prologで

rotate という操作があります。要素を回転させる操作です。
いろいろな場面で Prolog の強力さを目の当たりにするのですが、今回はこの rotate という操作について見ていきます。


なお rotate させるばあい、方向として右と左がありますが、考え方は同じなのでここでは右方向だけ考えることにします。


回せるだけ回す

たとえば次のような配列に対して、

[1, 2, 3]


要素を右にひとつ回すと、次のようになります。

[3, 1, 2]


つまり一番右端の要素が一番左側に移動します。

[配列の左側, 配列の右側]

という配列が、

[配列の右側, 配列の左側]

という配列に変換されたことを意味します。


これを踏まえて。
この操作を Prolog で実装すると、こうなります。

rotate(L1, L2) :-
  append(Left, Right, L1), % 配列の左の要素に、配列の右の要素を連結すると L1 になる
  append(Right, Left, L2). % 配列の右の要素に、配列の左の要素を連結すると L2 になる


実行。上のコードを rotate.prolog という名前のファイルに保存し、SWI-Prolog で実行します。

$ swipl rotate.prolog
?- rotatt([1,2,3], L2).
L2 = [1, 2, 3] ;
L2 = [2, 3, 1] ;
L2 = [3, 1, 2] ;
L2 = [1, 2, 3] ;
false.

上のコードでは rotate する量を指定していないので、取りうる結果すべてを出力できます(結果が出力されたらセミコロンを入力します。これ以上値がないばあい false を出力して停止します)。
値が4種類出力されているのは、要素が空の配列、空配列も分割した配列の右側あるいは左側として扱われているためです。

[ 空配列 | 1, 2, 3 ]
[ 1 | 2, 3 ]
[ 1, 2 | 3 ]
[ 1, 2, 3 | 空配列 ]

決められた回数だけ回す

分割したときの部分配列の長さを指定してすることで、特定の回数だけ回すことができるようになります。

具体的には。

rotate(L1, N, L2) :-
  length(Right, N),        % 分割した右側の要素の数は N
  append(Left, Right, L1),
  append(Right, Left, L2).


実行。

?- rotate([1,2,3], 1, L2).
L2 = [3, 1, 2] ;
false.

今回は回す量が決められているので、結果はひとつだけになりました。