prolog搜索列表

时间:2011-12-04 22:56:29

标签: prolog dcg

我想比较这些清单。给定函数(List1,List2),List1的长度为N,列表2的长度为M,N> M。

我想检查List2的任何排列是否恰好是List1的前M个字符。

例如

predicate([a,c,b,d,e],[a,b,c,d]).

应该是真的

predicate([a,c,b,e,d],[a,b,c,d]).

应该是假的。

谢谢。

3 个答案:

答案 0 :(得分:4)

通常在描述列表之间的关系时,在这种情况下DCG很方便:

perm_prefix(Ls1, Ls2) :- phrase(perm(Ls2), Ls1, _).

perm([])  --> [].
perm(Ls0) --> [L], { select(L, Ls0, Ls1) }, perm(Ls1).

示例案例:

?- perm_prefix([a,c,b,d,e],[a,b,c,d]).
true

?- perm_prefix([a,c,b,e,d],[a,b,c,d]).
false.

答案 1 :(得分:2)

使用permutation/2prefix/2谓词,您可以编写如下内容:

has_prefix_perm(List1, List2) :-
    permutation(List2, Permutation),
    prefix(Permutation, List1),
    !.

作为旁注并引用swi-prolog manual

  

请注意,长度为N的列表有N!即使是相当短的列表(10!= 3,628,800),排列和无限排列生成也变得非常昂贵。

所以我要注意不要使用过长的第二个列表来调用has_prefix_perm/2,特别是如果它不是模数排列的前缀,因为所有的情况都将被测试。

另一种方法是测试List1项是List2的成员,直到List2为空,这样你知道存在一个排列:

has_prefix_perm(_, []) :- !.
has_prefix_perm([Head1|List1], List2) :-
    once(select(Head1, List2, Rest)),
    has_prefix_perm(List1, Rest).

这样写的,我不会在非地名单上使用它,但看到你的OP我没有进一步搜索......

另一种方法是检查List1减少到List2的长度是否是List2的排列:

has_prefix_perm(List1, List2) :-
    length(List2, L),
    length(LittleL1, L),
    append(LittleL1, _, List1),
    permutation(LittleL1, List2),
    !.

另一种方式是...我想有很多方法可以做到这一点,只需选择一个不太可怕的复杂性并且适合你的风格! :)

我会亲自去找最后一个。

答案 2 :(得分:2)

这是另一个DCG解决方案。

perm(Xs,Ys) :- phrase(perm(Xs),[],Ys).

perm([])-->[].
perm([X|Xs])-->perm(Xs),ins(X).

ins(X),[X]-->[].
ins(X),[Y]-->[Y],ins(X).

归因:Moments of Prolog, exhibit 0