我正在审查即将进行的测试的一些练习,并且遇到困难。
给定一个整数列表L,定义谓词:add(L,S),它返回一个整数列表S,其中每个元素是L中所有元素之和到达相同位置的总和。
示例:
? - 添加([1,2,3,4,5],S)。
S = [1,3,6,10,15]。
所以我的问题是谓词定义的含义是什么?它看起来很一般。我读过一些帖子,但是他们提供的内容并不多。谢谢!
答案 0 :(得分:4)
这是一个很好的练习,可以熟悉两个重要的Prolog概念:
我们从一个非常简单的关系开始,将整数I
和整数S0
的和与新的S
相关联:
sum_(I, S0, S) :- S #= S0 + I.
根据您的Prolog系统,您可能需要一个指令,如:
:- use_module(library(clpfd)).
使用声明性整数运算。
其次,有一个强大的元谓词系列(见meta-predicate)称为scanl/N
,在Richard O'Keefe的Prolog library proposal中有描述,并已在某些系统中实施。在我们的例子中,我们只需要scanl/4
。
示例查询:
?- scanl(sum_, [1,2,3,4,5], 0, Sums). Sums = [0, 1, 3, 6, 10, 15].
事实上,更多比完成,因为我们可以在所有方向中使用它,例如:
?- scanl(sum_, Is, 0, Sums). Is = [], Sums = [0] ; Is = [_2540], Sums = [0, _2540], _2540 in inf..sup ; Is = [_3008, _3014], Sums = [0, _3008, _3044], _3008+_3014#=_3044 ; etc.
这是我们对真正关系解决方案的期望!
还要注意0
的出现是部分和列表中的第一个元素。它满足您对任务的文本描述,但不满足您发布的示例。我将这些作为练习对齐。
答案 1 :(得分:1)
定义谓词只是意味着编写一个执行问题所需要的谓词。 在您的问题中,您必须编写add / 2谓词的定义(“/ 2”表示它有两个参数)。你可以写下面的定义:
add(L,S):- add1(L,0,S).
add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 is Sum+H,NSum is Sum+H,add1(T,NSum,T1).
上面的谓词为您提供所需的输出。一个简单的例子:
?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].
我认为上述或类似的谓词是某人在测试中等待的东西。
上面谓词的问题在于,如果您查询例如:
?- add(S,L).
S = L, L = [] ;
ERROR: is/2: Arguments are not sufficiently instantiated
正如您所看到的,当您尝试询问谓词何时成功时,它会提供一个明显的解决方案,并且对于进一步的解决方案,它会引发错误。这不是一个非常好的财产。您可以使用模块CLPFD
来改进它:
:- use_module(library(clpfd)).
add(L,S):- add1(L,0,S).
add1([],_,[]).
add1([H|T],Sum,[H1|T1]):- H1 #= Sum+H,NSum #= Sum+H,add1(T,NSum,T1).
现在进行一些查询:
?- add([1,2,3,4,5],S).
S = [1, 3, 6, 10, 15].
?- add(S,[1,3,6]).
S = [1, 2, 3].
?- add(S,L).
S = L, L = [] ;
S = L, L = [_G1007],
_G1007 in inf..sup ;
S = [_G1282, _G1285],
L = [_G1282, _G1297],
_G1282+_G1285#=_G1307,
_G1282+_G1285#=_G1297 ;
...and goes on..
正如您现在所看到的,谓词可以提供您提出的任何信息!那是因为现在它有一个更多的关系行为,而不是之前因is/2
谓词而产生的功能行为。 (这些是用于改进谓词行为的更多信息。对于测试,您可能不允许使用库等...因此您可能只编写一个至少回答问题的简单解决方案。)