A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Essayez-le en ligne!
Définit un prédicat +/2
qui prend une chaîne (sous la forme d'une liste de codes de caractères) comme premier argument ( A
) et définit son deuxième argument (B
) à l'ordre de la rotation symétrique d'ordre le plus élevé.
Explication
Ce programme utilise le fait que l'ensemble des rotations symétriques sur une chaîne est un groupe cyclique et donc l'ordre de l'ensemble des rotations symétriques est égal à l'ordre de la rotation symétrique d'ordre le plus élevé. Ainsi, le programme est capable de calculer le résultat souhaité en trouvant le nombre total de rotations symétriques sur la chaîne d'entrée.
Explication du code
La majorité du levage lourd se fait par un appel au findall/3
prédicat. Le findall/3
prédicat trouve toutes les différentes valeurs possibles pour le premier argument ( X
dans ce cas) de telle sorte que l'expression donnée comme deuxième argument soit vraie ( (append(X,Y,A),append(Y,X,A))
, plus à ce sujet plus tard). Enfin, il stocke chacune de ces valeurs possibles X
sous forme de liste dans l'argument final ( [_|Z]
).
L'expression passée en findall/3
tant que deuxième arugment, (append(X,Y,A),append(Y,X,A))
utilise le append/3
prédicat pour spécifier celui X
concaténé avec certains encore indéfinisY
doit être égale à A
, la chaîne d'entrée, et que la même Y
concaténation avec X
doit également être égale à A
. Cela signifie qu'il X
doit y avoir un préfixe A
tel que s'il est supprimé de l'avant A
et ajouté à l'arrière, la chaîne résultante est la même que A
. L'ensemble de X
s avec cette propriété a presque une correspondance biunivoque avec les rotations symétriques de A
. Il y a toujours exactement un cas de double comptage qui est dû au fait que la chaîne vide et A
les préfixes deA
qui correspondent à la rotation 0 de A
. Depuis la 0
rotation deA
est toujours symétrique, la longueur de la liste résultante de X
s findall/3
sera supérieure de un au nombre de rotations symétriques surA
.
Pour résoudre le problème du double comptage, j'utilise la correspondance de motifs sur le troisième argument du findall/3
prédicat. Dans Prolog, les listes sont représentées par des paires de leur tête (le premier élément) et de leur queue (le reste). Ainsi , [_|Z]
représente une liste dont la queue est égale est égale à Z
. Cela signifie que la longueur de Z
est inférieure de un au nombre de préfixes trouvés par lefindall/3
prédicat et donc égale au nombre de rotations symétriques de A
. Enfin, j'utilise le length/2
prédicat pour définir B
la longueur de Z
.