检查连续元素之间的差异是否相同

时间:2018-09-28 12:47:47

标签: list prolog

我不熟悉在Prolog中使用算术。

我做了一些小程序,但主要涉及逻辑。我正在尝试实现一个函数,如果每对连续的元素对之间的差异相同或不同,则该函数将返回truefalse

我的输入看起来像这样:sameSeqDiffs([3, 5, 7, 9], 2) 我觉得我需要从列表中拆分前两个元素,找到它们的区别,然后将结果添加到新列表中。处理完所有元素后,检查新列表中的元素是否全部相同。

我已经教过一些Prolog,其中包括建立关系并进行查询,但这似乎不适用于Prolog。

Update1:​​到目前为止,这是我提出的。我是这种语法的新手,但是我的代码仍然出现错误,但是我希望它能传达我正在尝试做的一般想法。

diff([X,Y|Rest], Result):-
    diff([Y,Z|Rest], Result2):-
       Result2 = Result,
       Z - Y = Result.

Update2:我知道我仍然需要对这段代码做很多事情,但是这是我将一直待到本周末的地方,我还有其他事情要做。我想我对它的逻辑有了更多的了解,并且我认为只有在列表的其余部分中至少还有两件事要处理时,我才需要弄清楚如何运行函数的最后一行。

diff([X,Y|Rest], Result):-
    number(Y),
    Y-X=Result,
    diff([Rest], Result).

Update3:我相信我具有想要的功能。我注意到的唯一奇怪之处是,当我运行并输入以下内容时:sameSeqDiffs([3,5,7],2).我得到true,然后立即返回false。这是正确的操作还是我仍然缺少什么?

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

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

更新4:我对此发布了一个新问题。...这里是链接:Output seems to only test the very last in the list for difference function

2 个答案:

答案 0 :(得分:1)

Prolog的语法

语法有点不对:通常一个子句的头部像foo(X, Y, Z),然后是箭头(:-),然后是主体。该主体通常不包含任何箭头:-。因此第二个箭头:-没什么意义。

谓词和统一

第二个在Prolog谓词中没有 input output ,谓词是truefalse(当然,它也可能出错或获取陷入无限循环,但这通常是我们要避免的行为)。它通过 unifying 变量传达答案。例如,呼叫sameSeqDiffs([3, 5, 7, 9], X)。可以通过将X2统一来成功,然后谓词-如果正确实现,将返回true.

归纳定义

为了设计谓词,通常首先要提出一个归纳定义:一种定义由一个或多个基本情况以及一个或多个“递归”情况组成(谓词是由其自身的部分定义的。)

例如,在这里我们可以说:

  

(基本情况)对于正好两个元素[X, Y]的列表,假设sameSeqDiffs([X, Y], D)是{{1}之间的差异,则谓词D成立}和Y

在Prolog中,它看起来像:

X

(必须填写sameSeqDiffs([X, Y], D) :- ___. )。

现在对于归纳情况,我们可以根据自身定义___,尽管 not 当然具有相同的参数。在数学中,有时会定义函数 f ,例如 f(i)= 2×f(i-1);以例如 f(0)= 1 为基础。我们可以用类似的方式为sameSeqDiffs/2定义一个归纳案例:

  

(归纳大小写)对于包含两个以上元素的列表,鉴于前两个元素具有差异sameSeqDiffs/2,且列表中的所有元素都具有相同的差异。列表中除第一个元素外的所有元素,所有元素也具有差异D

在Prolog中,它看起来像:

D

Prolog中的算法

开始使用Prolog编程的人经常犯的一个错误是,他们认为,就像许多编程语言中常见的那样,Prolog在某些函子上添加了语义。

例如,人们可以认为sameSeqDiffs([X, Y, Z|T], D) :- ___, sameSeqDiffs(___, ___). 将减少A - 1。对于Prolog,这只是A,不是减号,或其他任何东西,只是一个函子。结果,Prolog将评估这些表达式。因此,如果您写-(A, 1),那么X = A - 1就是X

那么我们如何执行数字运算? Prolog系统具有谓词{{​​1}},该谓词通过将语义附加到右手边来评估右手边。因此,X = -(A,1)谓词将解释这个is/2is/2等函子((+)/2为负号,(-)/2为负号,等)。

因此我们可以评估一个表达式,例如:

(+)/2

,然后将(-)/2设置为A = 4, is(X, A - 1). ,而不是 X。 Prolog还允许编写3中缀,例如:

4-1

在这里您将需要使用它来计算两个元素之间的差异。

答案 1 :(得分:0)

第二次尝试非常接近。应该是

samediffs( [X,  Y | Rest], Result):-
    Result is Y - X,
    samediffs( [Y | Rest], Result).

您甚至不需要“从列表中拆分前两个元素”。这会照顾好自己。

如何?很简单:在谓词的第一个条目上调用samediffs( List, D),将尚未实例化的 D = Result实例化为列表中第二个元素与第一个元素之间的计算差通过呼叫Result is Y - X

在谓词的每个后续条目上,也就是说,对于列表中元素XY的每个后续,调用{{1} }将计算该对 的差,并检查该对和Result is Y - X的数值相等性,这时它保存先前计算的值。

如果它们不相等,则谓词将失败。

如果是,则递归将继续。

唯一缺少的是此递归的基本情况:

Result

如果一直是一个单例(甚至是空的)列表,这将使差异参数samediffs( [_], _Result). samediffs( [], _Result). 未被实例化。在这种情况下,它可以解释为检查谓词。单例(甚至是空的)列表中的元素之间肯定没有不相等的差异。


通常,......

_Result

......递归!