A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Pruébalo en línea!
Define un predicado +/2
que toma una cadena (en forma de una lista de códigos de caracteres) como su primer argumento ( A
) y establece su segundo argumento ( B
) en el orden de la rotación simétrica de mayor orden.
Explicación
Este programa utiliza el hecho de que el conjunto de rotaciones simétricas en una cadena es un grupo cíclico y, por lo tanto, el orden del conjunto de rotaciones simétricas es igual al orden de la rotación simétrica de mayor orden. Por lo tanto, el programa puede calcular el resultado deseado al encontrar el número total de rotaciones simétricas en la cadena de entrada.
Explicación del código
La mayor parte del trabajo pesado se realiza mediante una llamada al findall/3
predicado. El findall/3
predicado encuentra todos los diferentes valores posibles para el primer argumento ( X
en este caso) de modo que la expresión dada como el segundo argumento sea verdadera ( (append(X,Y,A),append(Y,X,A))
más sobre eso más adelante). Finalmente, almacena cada uno de estos posibles valores de X
como una lista en el argumento final ( [_|Z]
).
La expresión que se pasa findall/3
como el segundo argumento, (append(X,Y,A),append(Y,X,A))
usa el append/3
predicado para especificar que X
concatenado con algo aún indefinido Y
debe ser igual a A
, la cadena de entrada, y que el mismo Y
concatenado X
también debe ser igual a A
. Esto significa que X
debe ser un prefijo de A
tal manera que si se elimina del frente A
y se agrega a la parte posterior, la cadena resultante es la misma que A
. El conjunto de X
s con esta propiedad casi tiene una correspondencia uno a uno con las rotaciones simétricas de A
. Siempre hay exactamente un caso de doble conteo que se debe al hecho de que tanto la cadena vacía como A
los prefijos deA
que corresponden a la rotación 0 de A
. Dado que la 0
rotación de A
siempre es simétrica, la longitud de la lista resultante de X
s findall/3
será mayor que la cantidad de rotaciones simétricas en A
.
Para resolver el problema del conteo doble, utilizo la coincidencia de patrones en el tercer argumento del findall/3
predicado. En Prolog, las listas se representan como pares de su cabeza (el primer elemento) y su cola (el resto). Por lo tanto, [_|Z]
representa una lista cuya cola es igual a Z
. Esto significa que la longitud de Z
es menor que el número de prefijos encontrados por el findall/3
predicado y, por lo tanto, igual al número de rotaciones simétricas de A
. Finalmente, uso el length/2
predicado para establecer B
la longitud de Z
.