List 有极限的子序列

List 有极限的子序列,list,debugging,prolog,dcg,subsequence,List,Debugging,Prolog,Dcg,Subsequence,这是我的问题: 编写一个过程distance(List,Nemptylist,SubList)/3,检查SubList 是列表的子列表,项目之间的距离不超过N约束(N 实现为Nemptylist–一个N匿名变量列表)。假设列表 是完全实例化的。重复答案是允许的,只要他们的数量是有限的 例如,对于N=2: ?- distance( [a,t,d,r,a,n,c,b,c] , [_,_], [a,b,c] ). true ?- distance( [m,a,t,d,r,b,c,t] , [_,_]

这是我的问题:

编写一个过程
distance(List,Nemptylist,SubList)/3
,检查
SubList
列表
的子列表,项目之间的距离不超过
N
约束(
N
实现为
Nemptylist
–一个
N
匿名变量列表)。假设
列表
是完全实例化的。重复答案是允许的,只要他们的数量是有限的

例如,对于
N
=2:

?- distance( [a,t,d,r,a,n,c,b,c] , [_,_], [a,b,c] ).
true

?- distance( [m,a,t,d,r,b,c,t] , [_,_] , [a,b,c] ).
false

?- distance([a, t, d, r, a, n, c, b], [_, _], [a, b, c]).
false

?- distance([c, c, c, a, c, c, c], [_, _], [a]).
true.
我已经坐了几个小时,试图解决这个问题,并最终给出了一些例子 上面的工作,但后来我运行了一些测试,他们失败了

我目前的解决方案如下:

distance( L1 , L2 , [X]   ) :-
  member(X,L1) .
distance( L1 , L2 , [H|T] ) :-
  distance(L1,L2,T) ,
  append(Y,Z,L2) ,
  T=[Hs|Ts] ,
  append([H],Y,W) ,
  append(W,[Hs],R) ,
  sublist(R,L1) .

prefix(X,L) :- append(X, _, L).

suffix(X,L) :- append(_, X, L).

sublist(X,L) :- suffix(S,L) , prefix(X,S) .
当我尝试运行此测试时:

distance( [r,a,n,c,b,c],[],X) .
由于超出运行时错误,它失败


我调试了几个小时,真的很累。请帮我完成这项糟糕的任务。

以下是一个逐步解决方案,从一个不完整的定义开始:

distance_tentative(Xs, _Ys, Zs) :-
   phrase(( ..., seq(Zs), ... ), Xs).

... --> [] | [_], ... .

seq([]) --> [].
seq([E|Es]) --> [E], seq(Es).
这个解决方案太专业化了,因为它只描述而不描述。子序列是:

subseq([]) --> [].
subseq([E|Es]) --> [E], subseq(Es).
subseq(Es) --> [_], subseq(Es).
现在,我们想限制中介无关元素的数量。也就是说,我们希望将最后一条规则的应用限制在此列表参数的长度
LN

subseq_n([], _) --> [].
subseq_n([E|Es], LN) --> [E], subseq_n(Es, LN).
subseq_n(Es, [_|LN]) --> [_], subseq_n(Es, LN).
也许最后一条规则应该改为:

subseq_n(Es, [E|LN]) --> [E], subseq_n(Es, LN).
我怀疑问题陈述的翻译有问题。无论如何,现在我们有:

distance(Xs, Ys, Zs) :-
   phrase(( ..., subseq_n(Zs, Ys), ... ), Xs).
有很多多余的答案,但你说这是可以的

优化 在第一个
子q\u n//2
的第一个元素开始之间存在大量冗余,即模糊性;类似地,在结尾处的
subseq\u n//2
之间。此外,如果
Zs
为空,一个答案就足够了。简短的

distance(_Xs, _Ys, []).
distance(Xs, Ys, [Z|Zs]) :-
   phrase( ( ..., [Z], rsubseq_n(Zs, Ys), ... ), Xs).

rsubseq_n([], _) --> [].
rsubseq_n([E|Es], Ys) --> [E], rsubseq_n(Es, Ys).
rsubseq_n([E|Es], [_|Ys]) --> [_], rsubseq_n([E|Es], Ys).
请注意,“距离列表”现在仅在子序列中使用

该程序具有非常有利的终止特性:

因此,只有知道第一个参数才能使谓词终止

编辑:您的问题陈述不明确,其中距离
N
适用于:

。。。约束项之间的距离不超过N

这可能意味着总编辑距离不超过N,或每个连续对之间的距离。因此,假设每个连续对之间的距离意味着:

distanceII(_Xs, _Ys, []).
distanceII(Xs, Ys, [Z|Zs]) :-
   phrase( ( ..., [Z], rsubseq_d(Zs, Ys), ... ), Xs).

rsubseq_d([], _) --> [].
rsubseq_d([E|Es],Max) -->
   maxseq(Max),
   [E],
   rsubseq_d(Es, Max).

maxseq(_) --> [].
maxseq([_|Es]) --> [_], maxseq(Es).

我认为您的实施存在两个主要问题:

  • 您正在将
    NEmptyList
    中的元素与
    子列表(R,L1)
    中的
    列表中的元素统一起来。未来的
    子列表
    目标可能会失败,因为
    NEmptyList
    不会与
    列表中的任何
    N
    连续元素统一。如果您想使用append(这是可以的),您应该每次构建一个新的长度列表,最多
    N
    (见下文)

  • 您可以使用
    列表中相同的唯一序列验证
    子列表中的不同序列。要演示这一点,请尝试以下解决方案:

    ?- distance([a,a],[],[a,a,a,a,a,a]).
    true ;
    true ;
    false.
    
    distance(_, _, []).
    distance(List, NEmpty, Sublist):-
        append(_, Right, List),   % The first element can be anywhere in the list
        distance2(Right, NEmpty, Sublist).
    
    distance2([X|_], _, [X]).
    distance2(List, NEmpty, [X|Sublist]):-
        length(NEmpty, N),
        between(0, N, N1),
        length(AtMostNEmpty, N1), % Make a different list each time of length <N
        append([X|AtMostNEmpty], Right, List),
        distance2(Right, NEmpty, Sublist).
    
  • 以下是一个解决方案:

    ?- distance([a,a],[],[a,a,a,a,a,a]).
    true ;
    true ;
    false.
    
    distance(_, _, []).
    distance(List, NEmpty, Sublist):-
        append(_, Right, List),   % The first element can be anywhere in the list
        distance2(Right, NEmpty, Sublist).
    
    distance2([X|_], _, [X]).
    distance2(List, NEmpty, [X|Sublist]):-
        length(NEmpty, N),
        between(0, N, N1),
        length(AtMostNEmpty, N1), % Make a different list each time of length <N
        append([X|AtMostNEmpty], Right, List),
        distance2(Right, NEmpty, Sublist).
    
    距离(,,[])。 距离(列表、NEmpty、子列表):- 追加(\右,列表),%第一个元素可以在列表中的任何位置 距离2(右,NEmpty,子列表)。 距离2([X | X],[ux])。 距离2(列表,NEmpty,[X|子列表]:- 长度(NEmpty,N), 在(0,N,N1)之间, 长度(AtMostNEmpty,N1),%在每次长度时制作不同的列表