2017-09-25 103 views
0

我正在做一個練習,要求實施from_to/3,在這裏你給出了兩個數字作爲前兩個參數,而Prolog給你列出了它們之間的所有內容作爲結果。例如:​​會給R=[1,2,3,4,5]爲什麼這些類似的項目有不同的結果?

我寫了下面的程序:

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

通過查詢fromto(3,8,R)返回五個3的列表。不好。 正確的方式來處理這將是:

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在其他你正確的順序放置會得到反向列表。這不是很有效率,因爲每次你需要在列表中添加一個元素時,你需要遍歷所有的列表並將它放置在提供額外開銷的地方。

例:

?- fromto(3,8,L). 
L = [3, 4, 5, 6, 7, 8] ; 
false. 

你也可以使用DCG通過@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

相關問題