在Prolog中反转部分列表

时间:2009-12-16 23:58:07

标签: algorithm prolog

我对Prolog功能的目标如下:

给定两个列表x和y,如果y可以通过反转列表x的连续部分从x形成,则返回true。

例如,如果输入为x = [1,3,2,4],y = [1,2,3,4],则结果应为“true”,因为我们可以反转第二个和第三个元素x得到y。

我真的不知道,我需要一些帮助!

3 个答案:

答案 0 :(得分:2)

这是使用SICStus Prolog 4.3.1的直接实现:

:- use_module(library(lists)).

list_singlePartReversed(Xs,Ys) :-
    same_length(Xs,Ys),              % Xs and Ys are lists w/the same length
    dif(Xs,Ys),                      % Xs and Ys are not equal
    append(Prefix  ,Xs0   ,Xs),      % Xs and Ys have common prefix
    append(Prefix  ,Ys0   ,Ys),
    append(Part    ,Suffix,Xs0),     % Xs and Ys have common suffix
    append(Reversed,Suffix,Ys0),
    reverse(Part,Reversed).          % the rest of Xs is reversed in Ys

现在进行一些示例查询...首先,您在问题中发布的原始查询:

?- list_singlePartReversed([1,3,2,4], [1,2,3,4]).
yes

接下来,我们希望失败的一个简单案例:

?- list_singlePartReversed([1,4,3,2],[]).
no

所有可能的反转方法怎么样?

?- list_singlePartReversed([1,2,3,4], Xs).
Xs = [2,1,3,4] ? ;
Xs = [3,2,1,4] ? ;
Xs = [4,3,2,1] ? ;
Xs = [1,3,2,4] ? ;
Xs = [1,4,3,2] ? ;
Xs = [1,2,4,3] ? ;
no

如果第一个参数未实例化但第二个参数是?

,该怎么办?
?- list_singlePartReversed(Xs, [1,2,3,4]).
Xs = [2,1,3,4] ? ;
Xs = [3,2,1,4] ? ;
Xs = [4,3,2,1] ? ;
Xs = [1,3,2,4] ? ;
Xs = [1,4,3,2] ? ;
Xs = [1,2,4,3] ? ;
no

那么最常见的查询呢?我们是否得到了无限解集的公平枚举?

?- list_singlePartReversed(Xs,Ys).
Xs = [_A,_B],       Ys = [_B,_A],       prolog:dif([_A,_B],[_B,_A])             ? ;
Xs = [_A,_B,_C],    Ys = [_B,_A,_C],    prolog:dif([_A,_B,_C],[_B,_A,_C])       ? ;
Xs = [_A,_B,_C],    Ys = [_C,_B,_A],    prolog:dif([_A,_B,_C],[_C,_B,_A])       ? ;
Xs = [_A,_B,_C],    Ys = [_A,_C,_B],    prolog:dif([_A,_B,_C],[_A,_C,_B])       ? ;
Xs = [_A,_B,_C,_D], Ys = [_B,_A,_C,_D], prolog:dif([_A,_B,_C,_D],[_B,_A,_C,_D]) ? ...

答案 1 :(得分:1)

在算法上,你可以比较索引0,并找到它们的不同之处(称此索引为“a”),然后从n向后比较,直到它们不同(称此索引为“b”)。

然后从一个列表中的索引“a”反转到索引“b”,并比较列表(或子列表,无关紧要)以查看它们是否相同。如果是,则为真,否则为假。

当两个列表相同时,角落情况就是这样。这可以定义为true或false,具体取决于null集是否计为列表的连续部分。

Search forward for mismatch:
[1,2,3,4]
[1,3,2,4]
   ^-------a

Search backward for mismatch:
[1,2,3,4]
[1,3,2,4]
     ^-----b

Reverse sub-list from a to b in either list:
[1,3,2,4]  <-- Reversed sub-list indexed from 1-2
[1,3,2,4]

If equal, then true.

这有帮助吗?这假定存在单个反向子列表。

答案 2 :(得分:-1)

这是一种Prologish方式:

rev(X,Y) :- 
   append(X1,X2,X3),
   append(X3,X4,X),
   reverse(X2,X5),
   append(X1,X5,X6),
   append(X6,X4,Y),
   !.

示例:

?- rev([1,3,2,4],[1,2,3,4]).
true.

?- rev([1,4,3,2],[1,2,3,4]).
true.