输出似乎仅测试列表中的最后一项是否有差异函数

时间:2018-09-30 12:33:27

标签: list recursion prolog

链接到旧问题:Checking if the difference between consecutive elements is the same

我在其他问题中发布了进度,但是这是我的代码,这是我试图在Prolog中解决的问题。我希望函数根据每个数字之间的差异是否与我的最后一个参数相同来返回sameSeqDiffs([3,5,7],2)的结果。到目前为止,这是我要介绍的内容:

sameSeqDiffs([X,Y], Result):-
    A is Y - X,
    A = Result.

sameSeqDiffs([X,Y,Z|T], Result):-
    sameSeqDiffs([Y,Z|T], Result).

当我测试此代码时,它似乎可以用于某些输入,但显然不能用于其他输入:

enter image description here

3 个答案:

答案 0 :(得分:3)

您的解决方案存在一些问题:

sameSeqDiffs([X,Y,Z|T], Result):-
    sameSeqDiffs([Y,Z|T], Result).

在这里,您将完全忽略变量X和差异X-Y。

sameSeqDiffs([X,Y], Result):-
    Result is Y - X.

sameSeqDiffs([X,Y,Z|T], Result):-
    Result is Y - X,
    sameSeqDiffs([Y,Z|T], Result).

答案 1 :(得分:1)

从本质上讲,您忘记了一件事:计算递归情况下的差异:

sameSeqDiffs([X,Y], Result):-
    A is Y - X,
    A = Result.

sameSeqDiffs([X,Y,Z|T], Result):-
    Result is Y - X,
    sameSeqDiffs([Y,Z|T], Result).

因此,这里我们将ResultY之间的区别统一到X。我们用这种差异进行递归调用,这样“更深的”递归调用将与已经扎根的差异统一起来。如果差异不匹配,则谓词将失败。

您还可以通过在Result谓词调用中立即使用is/2,而不是先使用变量(A),然后统一来使第一个子句更优雅如此,

sameSeqDiffs([X,Y], Result):-
    Result is Y - X.

sameSeqDiffs([X,Y,Z|T], Result):-
    Result is Y - X,
    sameSeqDiffs([Y,Z|T], Result).

然后我们获得以下结果:

?- sameSeqDiffs([3, 5, 7], D).
D = 2 ;
false.

?- sameSeqDiffs([3, 5, 7], 2).
true ;
false.

?- sameSeqDiffs([3, 5, 7], 4).
false.

?- sameSeqDiffs([2, 3, 4], 1).
true ;
false.

?- sameSeqDiffs([2, 3, 4, 6], 2).
false.

?- sameSeqDiffs([2, 3, 4, 6], 1).
false.

它在false之后返回true的事实是由于Prolog回溯并旨在寻找另一个解决方案。因此,如果打印出true; false.,我们知道尝试成功,因此谓词成功。

答案 2 :(得分:0)

对于这样的问题,现在是学习CLP(FD)的好时机,这是Prolog用来对整数进行推理的部分:

same_seq_dif([X,Y], R) :- Y - X #= R.
same_seq_dif([X,Y,Z|T], R) :-
    Y - X #= R,
    same_seq_dif([Y,Z|T], R).

除了在提供完全实例化的列表时产生正确的结果外,它还知道如何处理更常见的情况:

| ?- same_seq_dif([X,5,7], R).

R = 2
X = 3 ? ;

no
| ?- length(L,3), same_seq_dif(L, 3), fd_labeling(L).

L = [0,3,6] ? ;

L = [1,4,7] ? ;

L = [2,5,8] ? ;

L = [3,6,9] ? ;

L = [4,7,10] ?
...

我正在使用GNU Prolog,因此是fd_labeling/1谓词。 SWI有一个类似的谓词label/1