A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
オンラインでお試しください!
+/2文字列(文字コードのリストの形式)を最初の引数(A)として受け取り、2番目の引数(B)を最高次数の対称ローテーションの順序に設定する述語を定義します。
説明
このプログラムは、文字列の対称回転のセットが循環グループであり、対称回転のセットの順序が最高次の対称回転の順序と等しいという事実を利用しています。したがって、プログラムは、入力文字列の対称回転の総数を見つけることにより、目的の結果を計算できます。
コード説明
重労働の大部分は、findall/3述部への呼び出しによって行われます。findall/3述語発見(最初の引数の全ての異なる可能な値はX2番目の引数として与えられた式は、(真であることをここでは)そのような(append(X,Y,A),append(Y,X,A))後、その上より)。最後に、これらの可能な値のそれぞれをXリストとして最後の引数([_|Z])に格納します。
findall/32番目のarugmentとして渡される式(append(X,Y,A),append(Y,X,A))は、append/3述語を使用して、X未定義の文字列と連結された文字列が入力文字列と等しくなければならず、同じ文字列と連結されている文字列もとY等しくなければならないことを指定します。これは、が前から削除されて後ろに追加された場合、結果の文字列がと同じになるようにするためのプレフィックスである必要があることを意味します。このプロパティを持つのセットは、の対称回転とほぼ 1対1で対応します。空の文字列との両方がプレフィックスであるという事実が原因で、二重カウントが必ず1つだけ発生します。AYXAXAAAXAAAの0回転に対応しAます。の0-rotation Aは常に対称であるため、結果のXsのリストの長さは、findall/3の対称回転の数よりも1つ大きくなりAます。
二重カウントの問題を解決するために、findall/3述語の3番目の引数にパターンマッチングを使用します。Prologでは、リストは頭(最初の要素)と尾(残り)のペアとして表されます。したがって[_|Z]、末尾が等しいに等しいリストを表しZます。つまり、の長さはZ、findall/3述語によって検出されたプレフィックスの数よりも1つ少ないため、の対称ローテーションの数と等しくなりAます。最後に、length/2述語を使用Bしての長さに設定しZます。