Prolog - >我有一个列表[X,...,Y,... Z],我如何得到一个只从X到Y的列表?

时间:2018-05-08 15:11:46

标签: prolog

SWI-PROLOG。
我有一个列表[X,...,Y,...,Z],如何获得一个仅从X到Y的列表?
那是[ X,...,Y ,...,Z] - > [X,...,Y]
我对这种语言知之甚少,所以欢迎所有的帮助! 我试过这个:

bla([Ele|_], Ele, _). 
bla([H|T], Ele, Res):-
   append(Res, H, New_Res),
   bla([T], Ele, New_Res).  

在这里,Ele将是Y.
我将Res作为空列表初始化。

我再说一遍,我对这种语言不熟悉,所以我写的可能是非常错的,抱歉!

3 个答案:

答案 0 :(得分:3)

使用append/3可能只是:

bla(L, Ele, NL):-
  append(NL1, [Ele|_], L),
  append(NL1, [Ele], NL).

当L3是L1和L2的串联时,注意到append(L1,L2,L3)成功,您可以使用第一个追加(append(NL1, [Ele|_], L))将项目从L提取到所需的项目,在此示例中,L2是一个以元素Ele开头的列表,因此L是一个以NL1开头且L的下一个元素为Ele的列表。

第二个附加用于将Ele添加到NL1的末尾。

不使用append/3,您可以写:

bla([Ele|_], Ele, [Ele]).
bla([E|L], Ele, [E|NL]):-
  bla(L, Ele, NL).

如果Ele在L中出现多次,则两次实施都可能成功多次,如果Ele没有出现在L中,则会失败。

答案 1 :(得分:3)

或者,由于您的谓词描述了两个列表和一个数据元素之间的关系,您可以选择将DCG用于该任务:

list_pivot_sublist(L,P,S) :-
   phrase(sublist_till(L,P),S).  % the sublist up to the pivot element
                                 % is described by the DCG sublist_till//2

sublist_till([P|_],P) -->        % if the head of the list is P
   [P].                          % it's the last element in the sublist
sublist_till([X|Xs],P) -->       % if the head of the list is any element X
   [X],                          % X is in the sublist and
   sublist_till(Xs,P).           % the same goes for the tail and P

现在让我们看一些问题:

什么是[1,2,3,4,5]的子列表到元素3?

?- list_pivot_sublist([1,2,3,4,5],3,S).
S = [1, 2, 3] ;
false.

[1,2,3,4,5]有哪些子列表 - 枢轴对?

?- list_pivot_sublist([1,2,3,4,5],P,S).
P = 1,
S = [1] ;
P = 2,
S = [1, 2] ;
P = 3,
S = [1, 2, 3] ;
P = 4,
S = [1, 2, 3, 4] ;
P = 5,
S = [1, 2, 3, 4, 5] ;
false.

子列表[1,2,3]的原始列表和拟合枢轴元素是什么样的?

?- list_pivot_sublist(L,P,[1,2,3]).
L = [1, 2, 3|_G4751],
P = 3 ;
false.

或最常见的查询:有哪些相应的列表,数据透视元素和子列表?

?- list_pivot_sublist(L,P,S).
L = [P|_G4739],
S = [P] ;
L = [_G4738, P|_G4745],
S = [_G4738, P] ;
L = [_G4738, _G4744, P|_G4751],
S = [_G4738, _G4744, P] ;
L = [_G4738, _G4744, _G4750, P|_G4757],
S = [_G4738, _G4744, _G4750, P] ;
.
.
.

这些与@ gusbro的bla/3版本相同的答案,但此查询除外...

?- bla(L,P,[1,2,3]).
L = [1, 2, 3|_G4739],
P = 3 ;

ERROR: Out of global stack

...在提供唯一答案后循环使用第一个版本(以append/3为目标的那个版本)。这样做的原因是第一个目标提供了无数的候选解决方案......

?- append(NL1, [Ele|_], L).
NL1 = [],
L = [Ele|_G900] ;
NL1 = [_G1000],
L = [_G1000, Ele|_G900] ;
NL1 = [_G1000, _G1006],                                   % this candidate leads to
L = [_G1000, _G1006, Ele|_G900] ;                         % the only solution
NL1 = [_G1000, _G1006, _G1012],
L = [_G1000, _G1006, _G1012, Ele|_G900] ;
.
.
.

...除了上面查询中标记的那个之外,所有这些都失败了:

?- append(NL1, [Ele|_], L), append(NL1, [Ele], [1,2,3]).
NL1 = [1, 2],                                             % corresponding answer
Ele = 3,                                                  % to the third candidate
L = [1, 2, 3|_G4641] ;                                    % above
ERROR: Out of global stack

因此,非append/3版本显然更可取。关于@lurker的评论,我还要注意,如果在列表中多次出现pivot元素,那么使用这些版本,您将获得多个答案:

?- list_pivot_sublist([1,2,3,4,5,3],3,S).
S = [1, 2, 3] ;
S = [1, 2, 3, 4, 5, 3] ;

如果您只想获得第一个子列表,可以通过添加约束来更改DCG版本,XP不同,这会阻止Prolog在第一次成功后进一步递归:< / p>

sublist_till([P|_],P) -->
   [P].
sublist_till([X|Xs],P) -->
   {dif(X,P)},                % <- new constraint
   [X],
   sublist_till(Xs,P).

现在上面的查询只得到一个答案:

?- list_pivot_sublist([1,2,3,4,5,3],3,S).
S = [1, 2, 3] ;
false.

最常见的查询也略有不同,因为现在它将dif/2约束传播到答案:

?- list_pivot_sublist(L,P,S).
L = [P|_G4739],
S = [P] ;
L = [_G4886, P|_G4890],
S = [_G4886, P],
dif(_G4886, P) ;
L = [_G4942, _G4945, P|_G4949],
S = [_G4942, _G4945, P],
dif(_G4942, P),
dif(_G4945, P) ;
.
.
.

你可以通过在递归规则中添加相同的约束来改变@ gusbro的第二个版本以体现相同的行为:

bla([Ele|_], Ele, [Ele]).
bla([E|L], Ele, [E|NL]):-
  dif(E,Ele),                  % <- new constraint
  bla(L, Ele, NL).

答案 2 :(得分:0)

没有append/3已经给出了你想要的东西吗?

?- append(L, [y|_], [x,x,x,y,x,y,x,z]).
L = [x, x, x] ;
L = [x, x, x, y, x] ;
false.

您可以重新添加最后一个&#39; y&#39;另一个调用append/3的元素:

?- append(L, [y|_], [x,x,x,y,x,y,x,z]), append(L, [y], L1).
L1 = [x, x, x, y] ;
L1 = [x, x, x, y, x, y] ;
false.