prolog - Prolog -> 我有一个列表 [X,...,Y,...Z],我如何获得一个仅从 X 到 Y 的列表?
问题描述
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
一个空列表。
我再说一遍,我是这种语言的新手,所以我写的可能非常错误,对不起!
解决方案
或者,由于您的谓词描述了两个列表和一个枢轴元素之间的关系,您可以选择使用 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 的评论,我还想指出,对于这些版本,如果枢轴元素在列表中多次出现,您将得到多个答案:
?- list_pivot_sublist([1,2,3,4,5,3],3,S).
S = [1, 2, 3] ;
S = [1, 2, 3, 4, 5, 3] ;
如果您只想获得第一个子列表,您可以通过添加一个约束来更改 DCG 版本,X
不同于P
,这可以防止 Prolog 在第一次成功后进一步递归:
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).
推荐阅读
- android - JavaPoet如何给Activity添加参数?
- php - 当我通过 config() 获取数组的键时,为什么它们会改变?
- docker - 运行多个 podman 容器,例如 docker-compose
- c# - Kinectv2 - 如何从 kinect fusion explorer 中删除深度颜色 - wpf 示例 c#?
- python - 年到世纪的功能代码理解
- php - Laravel Spatie SSR 节点命令不工作总是显示“节点”不被识别为内部或外部命令
- java - spring和hibernate访问数据库的同步方法
- swift - 从一个 UIStoryBoard 控制器切换到另一个 UIStoryBoard 控制器
- flutter - Flutter 中如何解析数据列表项下拉列表
- css - css动画中两个步骤之间如何平滑转换