A+B:-findall(X,(append(X,Y,A),append(Y,X,A)),[_|Z]),length(Z,B).
온라인으로 사용해보십시오!
술어 정의 +/2첫번째 인수로 (문자 코드의리스트의 형태로) 문자열을 얻어 ( A)과 두번째 인수 (설정 B최상위 대칭 회전의 순서로 참조).
설명
이 프로그램은 문자열의 대칭 회전 집합이 순환 그룹이므로 대칭 회전 집합의 순서가 최상위 대칭 회전의 순서와 동일하다는 사실을 사용합니다. 따라서 프로그램은 입력 문자열에서 총 대칭 회전 수를 찾아 원하는 결과를 계산할 수 있습니다.
코드 설명
무거운 리프팅의 대부분은 findall/3술어를 호출하여 수행됩니다 . findall/3술어 (첫번째 인수에 대한 모든 다른 가능한 값 발견 X번째 인수로 주어진 식 (사실임이 경우) 등 (append(X,Y,A),append(Y,X,A))나중에 그 온). 마지막으로 가능한 모든 값을 X최종 인수 ( [_|Z]) 의 목록으로 저장합니다 .
findall/3두 번째 arugment로 전달 된 표현식 (append(X,Y,A),append(Y,X,A))은 append/3술어를 사용하여 X아직 정의되지 않은 일부와 연결된 것은 입력 문자열 Y과 같아야하며 A, Y연결된 것과 동일한 X것은 같아야 함을 지정 A합니다. 이것은 X접두사가 A앞에 와서 제거되고 A뒤에 추가되는 경우 결과 문자열이와 같아야 한다는 접두사 여야합니다 A. X이 속성을 가진 의 세트는 의 회전에 대칭 회전과 거의 일대일 대응 관계를 갖습니다A . 빈 문자열과 A접두사 라는 사실로 인해 이중 계산의 경우는 항상 정확히 하나 입니다.A의 0 회전에 해당합니다 A. 이후 0의 회전이 A의 결과 목록의 대칭 길이 항상 X들에서 findall/3의 대칭 회전 수에 1을 더한 것입니다 A.
이중 계산 문제를 해결하기 위해 findall/3조건 자의 세 번째 인수에 패턴 일치를 사용합니다 . 프롤로그에서 목록은 머리 (첫 번째 요소)와 꼬리 (나머지)의 쌍으로 표시됩니다. 따라서 [_|Z]꼬리가 같은 목록을 나타냅니다 Z. 이는 길이 Z가 findall/3술어 에서 찾은 접두사 수보다 1이 작으므로 대칭 회전 수와 같습니다 A. 마지막으로 length/2조건자를 사용 B하여 길이 를 설정 합니다 Z.