A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Provalo online!
Definisce un predicato +/2che accetta una stringa (sotto forma di un elenco di codici carattere) come primo argomento ( A) e imposta il secondo argomento ( B) sull'ordine della rotazione simmetrica di ordine più elevato.
Spiegazione
Questo programma utilizza il fatto che l'insieme di rotazioni simmetriche su una stringa sono un gruppo ciclico e quindi l'ordine dell'insieme di rotazioni simmetriche è uguale all'ordine della rotazione simmetrica di ordine più elevato. Pertanto, il programma è in grado di calcolare il risultato desiderato trovando il numero totale di rotazioni simmetriche sulla stringa di input.
Spiegazione del codice
La maggior parte del sollevamento pesante viene effettuata tramite una chiamata al findall/3predicato. Il findall/3predicato trova tutti i diversi valori possibili per il primo argomento ( Xin questo caso) in modo tale che l'espressione fornita come secondo argomento sia vera ( (append(X,Y,A),append(Y,X,A)), più su questo più avanti). Infine memorizza ciascuno di questi possibili valori di Xcome elenco nell'argomento finale ( [_|Z]).
L'espressione passata findall/3come secondo arugment, (append(X,Y,A),append(Y,X,A))usa il append/3predicato per specificare che Xconcatenato con alcuni ancora indefiniti Ydeve essere uguale a A, la stringa di input e che anche lo stesso Yconcatenato Xdeve essere uguale a A. Ciò significa che Xdeve essere un prefisso Atale che se viene rimosso dalla parte anteriore Ae aggiunto alla parte posteriore, la stringa risultante è la stessa di A. L'insieme di Xs con questa proprietà ha quasi una corrispondenza uno a uno con le rotazioni simmetriche di A. Esiste sempre esattamente un caso di doppio conteggio che è causato dal fatto che sia la stringa vuota che i Aprefissi sonoAche corrisponde alla rotazione 0 di A. Poiché la 0rotazione di Aè sempre simmetrica, la lunghezza dell'elenco risultante di Xs da findall/3sarà uno maggiore del numero di rotazioni simmetriche su A.
Per risolvere il problema del doppio conteggio, utilizzo il pattern matching sul terzo argomento del findall/3predicato. In Prolog le liste sono rappresentate come coppie della loro testa (il primo elemento) e della coda (il resto). [_|Z]Rappresenta quindi un elenco la cui coda è uguale è uguale a Z. Ciò significa che la lunghezza di Zè uno in meno del numero di prefissi trovati dal findall/3predicato e quindi uguale al numero di rotazioni simmetriche di A. Infine, uso il length/2predicato per impostare Bla lunghezza di Z.