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
качестве второго arugment, (append(X,Y,A),append(Y,X,A))
использует append/3
предикат, чтобы указать, что X
конкатенация с некоторой, но еще не определенной, Y
должна быть равна A
входной строке, и что та же Y
конкатенация с X
должна быть также равна A
. Это означает, что X
должен быть некоторый префикс, A
такой, что если он будет удален с передней части A
и добавлен с обратной стороны, то результирующая строка будет такой же, как A
. Множество X
s с этим свойством почти имеет взаимно однозначное соответствие с симметричными поворотами A
. Всегда существует ровно один случай двойного счета, который вызван тем фактом, что как пустая строка, так и A
являются префиксамиA
которые соответствуют 0-вращению A
. Поскольку 0
-ротация A
всегда симметрична, длина результирующего списка X
s из findall/3
будет на единицу больше, чем число симметричных поворотов на A
.
Чтобы решить проблему двойного счета, я использую сопоставление с образцом для третьего аргумента findall/3
предиката. В Прологе списки представлены в виде пар их головы (первый элемент) и их хвоста (остальные). Таким образом [_|Z]
представляет список, хвост которого равен равен Z
. Это означает, что длина на Z
единицу меньше числа префиксов, найденных findall/3
предикатом, и, следовательно, равна количеству симметричных поворотов A
. Наконец, я использую length/2
предикат для установки B
длины Z
.