A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Provalo online!
Definisce un predicato +/2
che 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/3
predicato. Il findall/3
predicato trova tutti i diversi valori possibili per il primo argomento ( X
in 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 X
come elenco nell'argomento finale ( [_|Z]
).
L'espressione passata findall/3
come secondo arugment, (append(X,Y,A),append(Y,X,A))
usa il append/3
predicato per specificare che X
concatenato con alcuni ancora indefiniti Y
deve essere uguale a A
, la stringa di input e che anche lo stesso Y
concatenato X
deve essere uguale a A
. Ciò significa che X
deve essere un prefisso A
tale che se viene rimosso dalla parte anteriore A
e aggiunto alla parte posteriore, la stringa risultante è la stessa di A
. L'insieme di X
s 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 A
prefissi sonoA
che corrisponde alla rotazione 0 di A
. Poiché la 0
rotazione di A
è sempre simmetrica, la lunghezza dell'elenco risultante di X
s da findall/3
sarà 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/3
predicato. 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/3
predicato e quindi uguale al numero di rotazioni simmetriche di A
. Infine, uso il length/2
predicato per impostare B
la lunghezza di Z
.