프롤로그 쿼리 : 재귀 쿼리에서 더하기는 어떻게 중요합니까?
목록의 n 번째 요소를 찾기 위해 술어를 작성하려고합니다.
처음에는 다음과 같이 썼습니다.
nth([X|_], 0, X).
nth([_|T],N,Z):- N > 0, nth(T, M, Z), N is M + 1.
같은 쿼리에 대해 작동 nth([1, 2, 3, 4, 5], 0, X).
하지만 같은 쿼리의 nth([1, 2, 3, 4, 5], N, 1).
경우 ";"를 입력 한 후 "인수가 충분하지 않게 인스턴스화 된 오류"가 발생합니다. 답을 얻은 후. 이 경우 ans가 1 개뿐이라는 것을 알고 있지만 완전성을 위해 이유를 알고 싶습니다.
내가 스택 오버 플로우에서 읽을 여기에 다음이 더 나은 해결책이 :
nth([X|_], 0, X) :- !.
nth([_|Y], N, Z) :- N > 0, M is N-1, nth(Y, M, Z).
내 대답 M is N-1, nth(Y, M, Z).
에 반대되는 이유를 이해하고 싶습니다 nth(T, M, Z), N is M + 1
.
추신 : 질문 제목이 개선 될 수 있다고 생각하지만 어떻게해야할지 모르겠습니다. 제안 사항이 있으면 알려주십시오!
답변
is/2
완전한 제약 솔버가 아닙니다. 그래서 N is M + 1
및 M is N - 1
모양 동등하지만 그들은 없습니다합니다. 첫 번째는 M이 인스턴스화 될 때만 성공하고 두 번째는 N이 인스턴스화 될 때만 성공합니다. 인덱스가 0이 아닌 솔루션을 사용해 보셨습니까? 작동하지 않습니다. plus(1, M, N)
둘 중 하나 대신 사용 하여 작동하도록 할 수 있습니다. 또한 절 순서가 중요하므로에 plus(1, M, N)
대한 재귀 호출 이전에 있어야합니다 nth
.
nth([X|_], 0, X).
nth([_|T],N,Z):- N > 0, plus(1, M, N), nth(T, M, Z).
N > 0, nth(T, M, Z), plus(1, M, N)
절 순서 인 경우 M이 아직 인스턴스화되지 않았기 때문에 프로그램이 nth(T, M, Z)
먼저 만족을 시도하고 N > 0
인스턴스화되지 않은 오류를 발생시킵니다 .
또한 생성적인 경우에는 어느 프로그램도 작동하지 않습니다.