A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Спробуйте в Інтернеті!
Визначає предикат, +/2який приймає рядок (у вигляді списку кодів символів) як свій перший аргумент ( A) і встановлює свій другий аргумент ( B) у порядку симетричного обертання вищого порядку.
Пояснення
Ця програма використовує той факт, що безліч симетричних обертів на рядку є циклічною групою, і тому порядок набору симетричних обертів дорівнює порядку симетричного обертання вищого порядку. Таким чином програма здатна обчислити бажаний результат, знайшовши загальну кількість симетричних обертів на вхідній рядку.
Пояснення коду
Більшість важких підйомів здійснюється за викликом до findall/3присудка. findall/3Предикат знаходить все різні можливі значення для першого аргументу ( Xв даному випадку) , так що вираз , наведене в якості другого аргументу є істинним ( (append(X,Y,A),append(Y,X,A)), про це пізніше). Нарешті, воно зберігає кожне з цих можливих значень Xяк список у заключному аргументі ( [_|Z]).
Вираз, переданий findall/3як другий рухомий фрагмент, (append(X,Y,A),append(Y,X,A))використовує append/3присудок, щоб вказати, що Xоб'єднане з деяким ще не визначеним Yрівнем має бути Aвхідним рядком, а також те, що Yз'єднане з цим Xтакож повинно бути рівним A. Це означає, що Xповинен бути якийсь такий префікс A, що якщо його вилучити з передньої частини Aта додати до задньої частини, то результуюча рядок буде такою самою, як A. Множина Xs з цією властивістю майже має однозначну відповідність симетричним обертанням A. Завжди рівно один випадок подвійного підрахунку, який викликаний тим, що як порожній рядок, так і AпрефіксиAякі відповідають 0-обертанню A. Оскільки 0-обертання Aзавжди симетричне, довжина результуючого списку Xs від findall/3буде на один більша, ніж кількість симетричних обертань на A.
Для вирішення задачі подвійного підрахунку я використовую відповідність шаблону на третьому аргументі findall/3присудка. У списках Пролога представлені у вигляді пар голови (перший елемент) та хвоста (решта). Таким чином, [_|Z]представлений список, хвіст якого дорівнює, дорівнює Z. Це означає, що довжина на Zодин менше кількості префіксів, знайдених findall/3присудком і, таким чином, дорівнює кількості симетричних обертів A. Нарешті, я використовую length/2присудок, щоб встановити Bдовжину Z.