2017-09-25 3 views
0

from_to/3을 구현하도록 요청한 연습을하고 있었는데 처음 두 개의 인수로 두 개의 숫자를주고 Prolog는 결과 사이에 모든 것의 목록을 제공합니다. 예 : from_to(1,5,R)R=[1,2,3,4,5]이됩니다. 이 다섯 가지 삼의 목록을 반환 쿼리 fromto(3,8,R)이러한 유사한 프로그램의 결과가 다른 이유는 무엇입니까?

fromto(N, O, []):- 
    N >= O. 
fromto(N, O, [N|TailResult]):- 
    O > N, 
    O1 is O-1, 
    fromto(N, O1, TailResult). 

:

나는 다음과 같은 프로그램을 썼습니다. 안좋다. 올바른 방법은 될 것이라고 처리하기 : 의도 한대로

from_to(N, O, []) :- 
    N > O. 
from_to(N, O, [N|TailResult]) :- 
    N =< O, 
    N1 is N + 1, 
    from_to(N1, O, TailResult). 

이것은 list 3,4,5,6,7,8을 제공합니다.

제 질문은 이것이 어떻게 작동하는지입니다. 프로그램은 내가 O와 함께 아래에서 아래로 작업 한 점과 N에 추가하여 올바른 것으로 작동한다는 점만 다릅니다. 그러나 결과는 완전히 다릅니다. 이 문제의 원인을 아는 사람이 있습니까?

답변

2

문제는 첫 번째 시도에서 첫 번째 인수 -N은 O 변경 만 변경하지 않고 목록에 N을 반복적으로 배치하므로 모든 것이 N의 목록이라는 것을 알 수 있습니다. 당신이 목록의 각 시간 O를 배치 할 수있는이 방법을 유지하려면

:

fromto(N, O, []):- 
    N > O. 
fromto(N, O, L):- 
    O >= N, 
    O1 is O-1, 
    fromto(N, O1, L2), 
    append(L2,[O],L). 

이 구현의 문제는 당신이 다른 사람을 올바른 순서로 배치하기 위해 append/3를 사용할 필요가있다 역 목록을 얻을 것이다. 목록에 요소를 추가해야 할 때마다 모든 목록을 탐색하여 추가 오버 헤드를주는 ende에 배치해야하므로 효율적이지 않습니다.

예 :

또한 @false에 의해 제안 당신은 DCG를 사용할 수
?- fromto(3,8,L). 
L = [3, 4, 5, 6, 7, 8] ; 
false. 

:

from_to(N,N) -->[N]. 
from_to(N,O) --> [N],{N<O, N1 is N+1},from_to(N1,O). 

final_solution(N,O,L):- phrase(from_to(N,O),L). 

을 그리고 다른 방법 (O 대신 N의 감소) :

from_to(N,N) -->[N]. 
from_to(N,O) --> {N<O, O1 is O-1},from_to(N,O1),[O]. 

final_solution(N,O,L):- phrase(from_to(N,O),L). 

이제 두 가지 해결 방법은 두 번째 절의 순서를 변경하는 것과 매우 비슷합니다.

+1

'append/3'을 사용하는 대신 [tag : dcg] -notation을 사용하여 두 가지 접근법을 공식화하는 것이 더 통찰력이 있습니다. – false

+0

@false 당신은 바로 dcg 솔루션을 추가했습니다. – coder

관련 문제