A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Cobalah online!
Mendefinisikan predikat +/2
yang mengambil string (dalam bentuk daftar kode karakter) sebagai argumen pertama ( A
) dan menetapkan argumen kedua ( B
) ke urutan rotasi simetris urutan tertinggi.
Penjelasan
Program ini menggunakan fakta bahwa himpunan rotasi simetris pada string adalah grup siklik sehingga urutan himpunan rotasi simetris sama dengan urutan rotasi simetris urutan tertinggi. Dengan demikian program ini dapat menghitung hasil yang diinginkan dengan menemukan jumlah total rotasi simetris pada string input.
Penjelasan Kode
Mayoritas pengangkatan berat dilakukan dengan panggilan ke findall/3
predikat. The findall/3
predikat menemukan semua nilai yang berbeda yang mungkin untuk argumen pertama ( X
dalam kasus ini) sehingga ekspresi yang diberikan sebagai argumen kedua adalah benar ( (append(X,Y,A),append(Y,X,A))
lebih pada nanti). Akhirnya ia menyimpan masing-masing nilai yang mungkin X
sebagai daftar dalam argumen terakhir ( [_|Z]
).
Ekspresi dilewatkan findall/3
sebagai arugment kedua, (append(X,Y,A),append(Y,X,A))
menggunakan append/3
predikat untuk menentukan bahwa X
digabungkan dengan beberapa belum terdefinisi Y
harus sama dengan A
, string input, dan bahwa Y
digabungkan dengan yang sama X
juga harus sama dengan A
. Ini berarti bahwa X
harus ada beberapa awalan A
sehingga jika dihapus dari depan A
dan ditambahkan ke belakang maka string yang dihasilkan sama dengan A
. Himpunan X
s dengan properti ini hampir memiliki korespondensi satu-ke-satu dengan rotasi simetris A
. Selalu ada satu kasus penghitungan ganda yang disebabkan oleh fakta bahwa string kosong dan A
awalanA
yang sesuai dengan 0-rotasi A
. Karena 0
-rotasi A
selalu simetris, panjang dari daftar X
s yang dihasilkan findall/3
akan lebih besar dari jumlah rotasi simetris yang aktif A
.
Untuk mengatasi masalah penghitungan ganda, saya menggunakan pencocokan pola pada argumen ketiga dari findall/3
predikat. Dalam daftar Prolog diwakili sebagai pasangan kepala mereka (elemen pertama) dan ekor mereka (sisanya). Dengan demikian [_|Z]
mewakili daftar yang ekornya sama dengan Z
. Ini berarti bahwa panjang Z
satu kurang dari jumlah awalan yang ditemukan oleh findall/3
predikat dan dengan demikian sama dengan jumlah rotasi simetris A
. Akhirnya, saya menggunakan length/2
predikat untuk mengatur B
panjang Z
.