A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
Wypróbuj online!
Definiuje predykat, +/2który jako pierwszy argument przyjmuje ciąg (w postaci listy kodów znaków A) i ustawia drugi argument (B ) na kolejności symetrycznej rotacji najwyższego rzędu.
Wyjaśnienie
Ten program wykorzystuje fakt, że zbiór symetrycznych obrotów na sznurku jest grupą cykliczną, a zatem rząd zbioru symetrycznych rotacji jest równy rzędowi symetrycznego obrotu najwyższego rzędu. W ten sposób program jest w stanie obliczyć pożądany wynik, znajdując całkowitą liczbę symetrycznych obrotów na ciągu wejściowym.
Objaśnienie kodu
Większość ciężkich operacji podnoszenia odbywa się przez wezwanie do findall/3orzeczenia. findall/3Orzeczenie wyszukuje wszystkie inne możliwe wartości pierwszego argumentu ( Xw tym przypadku) w taki sposób, że ekspresja podano jako drugi argument jest prawdą ( (append(X,Y,A),append(Y,X,A))bardziej na później). Na koniec przechowuje każdą z tych możliwych wartości Xjako listę w końcowym argumencie ( [_|Z]).
Wyrażenie przekazane findall/3jako drugi argument (append(X,Y,A),append(Y,X,A))używa append/3predykatu do określenia, że Xkonkatenacja z niektórymi jeszcze niezdefiniowanymi Ymusi być równa Ałańcuchowi wejściowemu i że to samo Ykonkatenowane z Xmusi również być równe A. Oznacza to, że Xmusi to być jakiś prefiks, Atak że jeśli zostanie usunięty z przodu Ai dodany z tyłu, powstały ciąg będzie taki sam jak A. Zbiór Xs o tej właściwości ma prawie jeden do jednego związek z symetrycznymi obrotami A. Zawsze występuje dokładnie jeden przypadek podwójnego liczenia, który jest spowodowany faktem, że zarówno pusty ciąg znaków, jak i AprzedrostkiAktóre odpowiadają obrotowi 0 z A. Ponieważ 0obrót Ajest zawsze symetryczny, długość wynikowej listy Xs od findall/3będzie o jeden większa niż liczba symetrycznych obrotów na A.
Aby rozwiązać problem podwójnego liczenia, używam dopasowania wzorca do trzeciego argumentu findall/3predykatu. W listach prologów są reprezentowane jako pary głowy (pierwszy element) i ogona (reszta). Zatem [_|Z]reprezentuje listę, której ogon jest równy, jest równy Z. Oznacza to, że długość Zjest o jeden mniejsza niż liczba przedrostków znalezionych w findall/3predykacie, a zatem równa liczbie obrotów symetrycznych A. Na koniec używam length/2predykatu, aby ustawić Bdługość Z.