목록 내에서 술어 발생 찾기
목록 내에서 반전의 양을 찾으려고합니다. 역전 모든 쌍으로 정의 될 a,b
리스트에서 ai
의 인덱스 a
와 bi
의 인덱스 b
를 만족 a > b
하고 ai < bi
. 기본적으로 a는 b보다 먼저 나오지만 b보다 큽니다.
내가 한 첫 번째 일은 인덱스가 무엇인지 알아 내기 위해 술어를 작성하는 것이 었습니다.
indexOf(Index, Element, List) :-
nth1(Index, List, Element).
그런 다음 두 숫자의 집합이 반전인지 확인하기 위해 술어를 작성했습니다.
isInversion(A, B, List) :-
A \= B, indexOf(AI, A, List), indexOf(BI, B, List), A > B, AI < BI.
이 시점에서 저는 많은 질문을합니다. 특히 저는 논리 프로그래밍 언어에 익숙하지 않기 때문입니다. 내 첫 번째 질문은 indexOf가 실제로 인덱스를 제공하지 않습니까? 나는 그것이 본질적으로 모든 숫자를 시도해야 할 것처럼 보이므로 실제로 어떻게 작동하는지 혼란 스럽습니다.
어떻게 든 indexOf가 색인을 자동으로 결정하고 예상대로 AI / BI에 저장하면 isInversion 술어가 올바르게 평가 될 것이라고 믿습니다. 틀렸다면 알려주십시오.
내 주요 관심사는 실제로 반전의 양을 결정하는 방법입니다. 파이썬과 같은 일에서 나는 할 것입니다.
count = 0
for a in puzzle
for b in puzzle
if a is b continue
if isInversion(a, b, puzzle)
count = count + 1
그것은 내 반전의 양을 줄 것입니다. 그러나 프롤로그에서 어떻게 할 수 있습니까? For 루프는 그다지 문체 적이 지 않아서 사용하고 싶지 않습니다.
주목할 점은 다른 질문을 검색했습니다. 내가 뭘 찾고 있는지 정확히 모르기 때문에 조금 힘들다. 그러나 Prolog 와 같은 것들이 List의 모든 쌍에 대해 술어를 한다고 느꼈다는 것을 분명히하고 싶었습니다 . 제가 질문에 답하는 데 도움이되지 않았습니다.
답변
A\=B
바인딩되지 않은 변수로 인해 실패 하므로 제약 조건 을 제거해야 합니다.
그런 다음을 사용 aggregate_all/3하여 모든 반전을 계산합니다 (실제로 반전의 A / B 값이 필요하지 않음).
isInversion(A, B, List):-
indexOf(AI, A, List),
indexOf(BI, B, List),
A > B,
AI < BI.
countInversions(List, N):-
aggregate_all(count, isInversion(_, _, List), N).
샘플 실행 :
?- countInversions([4,3,2,1,9], N).
N = 6.
findall/3isInversion에서 사용하여 존재하는 반전을 볼 수 있습니다 .
?- findall(A-B, isInversion(A,B,[4,3,2,1,9]), LInversions).
LInversions = [4-3, 4-2, 4-1, 3-2, 3-1, 2-1].