목록 내에서 술어 발생 찾기

Nov 19 2020

목록 내에서 반전의 양을 찾으려고합니다. 역전 모든 쌍으로 정의 될 a,b리스트에서 ai의 인덱스 abi의 인덱스 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의 모든 쌍에 대해 술어를 한다고 느꼈다는 것을 분명히하고 싶었습니다 . 제가 질문에 답하는 데 도움이되지 않았습니다.

답변

2 gusbro Nov 19 2020 at 11:13

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].