2017-09-25 67 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

相关问题