在Prolog中交换列表的前两个元素

时间:2017-02-17 23:29:15

标签: prolog

我正在Learn Prolog Now进行此练习:

  

练习4.4
  写一个谓词swap12(List1,List2)来检查List1是否是   与List2相同,只是交换了前两个元素。

这是我到目前为止所做的:

swap12([],[]).
swap12([a, b | Ta], [b, a | Tb]) :- swap12(Ta, Tb).

但是当我尝试评估这个时,我得到以下结果:

?- swap12(X, Y).
X = Y, Y = [] ;
X = [a, b],
Y = [b, a] ;
X = [a, b, a, b],
Y = [b, a, b, a] .

我做错了什么?

目标是拥有以下内容:

swap12(X,Y).
X = [a, b].
Y = [b, a].
X = [a, b, b].
Y = [b, a, a].

等。请帮忙!

1 个答案:

答案 0 :(得分:1)

第一句:

swap12([],[]).

说交换空列表的前两个元素是空列表。我想,也许,根据定义,人们可能会这样说。但由于空列表没有元素,因此可能不会被认为是真的。

你的第二个条款是:

swap12([a, b | Ta], [b, a | Tb]) :- swap12(Ta, Tb).

如果您交换[a, b | Ta]的前两个元素,那么如果[b, a | Tb]TbTa的前两个元素已交换,则结果为a 。这是以ba开头的任何列表的规则,但如果您有任何其他前两个元素,则该规则将无效,因为bswap12([1,2,3,4], L) atoms ,而不是变量。因此,例如,1将失败,因为您的列表以2a开头,而不是bswap12(Ta, Tb)。此外,您的问题是交换 ONLY 前两个元素,而您的解决方案具有递归调用?- swap12([a,b], R). R = [b,a]. ?- swap12([b,a], R). false. % This fails because `b`, `a` doesn't match `a`, `b`. ?- swap12([a,b,c], R). false. % This fails because [a,b,c] has an odd number of elements ?- swap12([a,b,c,d], R). false. % This fails because `c`, `d` doesn't match `a` and `b` ?- swap12([a,b,a,b], R). R = [b, a, b, a]. ?- swap12(X, Y). X = Y, Y = [] ; X = [a, b], Y = [b, a] ; X = [a, b, a, b], Y = [b, a, b, a] ; X = [a, b, a, b, a, b], Y = [b, a, b, a, b, a] ; X = [a, b, a, b, a, b, a, b], Y = [b, a, b, a, b, a, b, a] ; ... ,它继续以递归方式交换。

以下是您的代码实际执行的操作(它不会执行您在问题中显示的内容,这意味着您显示的结果是针对您编写的代码的不同版本)。

a

最后一次执行显示了您的规则的真正含义。仅当第一个列表为空或任意数量的ba对且第二个列表相同且每个bb对交换为{时,它才会成功{1}},a

让我们重新开始吧。同样,问题是创建一个规则,如果第二个列表是 ONLY 交换的前两个元素的第一个列表,则该规则为true。具有至少两个元素的列表看起来像[X, Y|T](前两个元素是XY - 变量)。如果我想交换 ONLY 前两个元素,我会写[Y, X|T]所以我换了XY,但保持相同 tail,T(我不想再交换任何元素)。

因此,该规则看起来像:

swap12([X, Y|T], [Y, X|T]).

这表示如果我有一个列表[X, Y|T],那么[Y, X|T]是相同的列表,但只交换了前两个元素。你可以尝试一下:

?- swap12([a], R).
false.       % fails because `[a]` only has one element!

?- swap12([a,b], R).
R = [b, a].

?- swap12([a,b,c], R).
R = [b, a, c].

?- swap12([a,b,c,d], R).
R = [b, a, c, d].

?- swap12([a,b,c,e,f], R).
R = [b, a, c, e, f].

?- ...