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