Prolog 获取列表 PROLOG 提供的项目之间的项目
Prolog get items between the items supplied from a list PROLOG
我正在尝试在 prolog 中构建一个列表函数,希望它能执行以下操作;
split(1, 4, [1, 2, 3, 4]). [2, 3]
split(2, 4, [1, 2, 3, 4, 5]). [3]
也就是说,它将所有项目放在一个列表中,出现在所提供的两个值之间。
我尝试了什么;
split(Start, Finish, List) :- append(List, _, [Start|Xs]),
append([Finish|Xs], _, List).
我似乎永远无法让它工作!我是序言的新手,所以请相对友好!!
谢谢
编辑
好的,我有一个解决方案,想知道它是否可以改进。解决方案如下,
% Split a list at a specified index
split(List, Index, Front, Back) :-
length(Front, Index),
append(Front, Back, List).
% Get list items inbetween members
inbetween(List, From, To, Result) :-
nth1(FromI, List, From),
nth0(ToI, List, To),
split(List, FromI, _, List1),
split(List, ToI, _, List2),
subtract(List1, List2, Result).
如您所见,我遵循了评论中的建议并进行了一些调整。这有什么改进吗?
谢谢,(甚至可以在一个谓词中实现吗?)
示例
inbetween([1,2,3,4,5,6], 2, 5, Result). % [3,4]
inbetween([a,b,c,d,e,f], a, e, Result). % [b,c,d]
我认为您提出的解决方案很有趣,只需稍作调整即可使其正常工作:
% Split a list at a specified index
split(List, Index, Front, Back) :-
length(Front, Index),
append(Front, Back, List).
% Get list items inbetween members
inbetween(List, From, To, Result) :-
nth1(FromI, List, From),
split(List, FromI, _, List1),
nth0(ToI, List1, To),
split(List1, ToI, Result, _).
split/4
谓词与您所拥有的没有变化。我对 inbetween/4
主谓词做了一些修改,首先它会找到 From
之后的所有内容,然后 使用该结果 并找到 [=19= 之前的所有内容] 产生最终结果。
| ?- inbetween([a,b,c,a,x,b,e,f], a, b, L).
L = [] ? ;
L = [b,c,a,x] ? ;
L = [x] ? ;
(1 ms) no
使用 append/3
的较短版本是:
betwixt2(List, A, B, Result) :-
append(_, [A|T], List),
append(Result, [B|_], T).
另一种更基于递归且不使用库调用的方法是:
inbetween(List, A, B, Result) :-
split_left(List, A, R),
split_right(R, B, Result).
split_left([X|T], X, T).
split_left([_|T], X, R) :- split_left(T, X, R).
split_right([X|_], X, []).
split_right([H|T], X, [H|R]) :- split_right(T, X, R).
最后,有一个有趣的、简洁的解决方案,我在发表评论时没有考虑过,使用更透明的 DCG:
betwixt(A, B, M) --> anything, [A], collect(M), [B], anything.
anything --> [].
anything --> [_], anything.
collect([]) --> [].
collect([H|T]) --> [H], collect(T).
inbetween(List, A, B, Result) :- phrase(betwixt(A, B, Result), List).
本例中的 DCG 很好地说明了正在发生的事情,结果与上述相同。为简洁起见,我也可以在第一个子句中使用 collect(_)
代替 anything
,但不想浪费未使用的参数。
要使用记入@false 的漂亮符号,我们可以使用 ...
作为术语,如下所示:
betwixt(A, B, M) --> ..., [A], collect(M), [B], ... .
... --> [].
... --> [_], ... .
collect([]) --> [].
collect([H|T]) --> [H], collect(T).
我正在尝试在 prolog 中构建一个列表函数,希望它能执行以下操作;
split(1, 4, [1, 2, 3, 4]). [2, 3]
split(2, 4, [1, 2, 3, 4, 5]). [3]
也就是说,它将所有项目放在一个列表中,出现在所提供的两个值之间。
我尝试了什么;
split(Start, Finish, List) :- append(List, _, [Start|Xs]),
append([Finish|Xs], _, List).
我似乎永远无法让它工作!我是序言的新手,所以请相对友好!!
谢谢
编辑
好的,我有一个解决方案,想知道它是否可以改进。解决方案如下,
% Split a list at a specified index
split(List, Index, Front, Back) :-
length(Front, Index),
append(Front, Back, List).
% Get list items inbetween members
inbetween(List, From, To, Result) :-
nth1(FromI, List, From),
nth0(ToI, List, To),
split(List, FromI, _, List1),
split(List, ToI, _, List2),
subtract(List1, List2, Result).
如您所见,我遵循了评论中的建议并进行了一些调整。这有什么改进吗?
谢谢,(甚至可以在一个谓词中实现吗?)
示例
inbetween([1,2,3,4,5,6], 2, 5, Result). % [3,4]
inbetween([a,b,c,d,e,f], a, e, Result). % [b,c,d]
我认为您提出的解决方案很有趣,只需稍作调整即可使其正常工作:
% Split a list at a specified index
split(List, Index, Front, Back) :-
length(Front, Index),
append(Front, Back, List).
% Get list items inbetween members
inbetween(List, From, To, Result) :-
nth1(FromI, List, From),
split(List, FromI, _, List1),
nth0(ToI, List1, To),
split(List1, ToI, Result, _).
split/4
谓词与您所拥有的没有变化。我对 inbetween/4
主谓词做了一些修改,首先它会找到 From
之后的所有内容,然后 使用该结果 并找到 [=19= 之前的所有内容] 产生最终结果。
| ?- inbetween([a,b,c,a,x,b,e,f], a, b, L).
L = [] ? ;
L = [b,c,a,x] ? ;
L = [x] ? ;
(1 ms) no
使用
append/3
的较短版本是:
betwixt2(List, A, B, Result) :-
append(_, [A|T], List),
append(Result, [B|_], T).
另一种更基于递归且不使用库调用的方法是:
inbetween(List, A, B, Result) :-
split_left(List, A, R),
split_right(R, B, Result).
split_left([X|T], X, T).
split_left([_|T], X, R) :- split_left(T, X, R).
split_right([X|_], X, []).
split_right([H|T], X, [H|R]) :- split_right(T, X, R).
最后,有一个有趣的、简洁的解决方案,我在发表评论时没有考虑过,使用更透明的 DCG:
betwixt(A, B, M) --> anything, [A], collect(M), [B], anything.
anything --> [].
anything --> [_], anything.
collect([]) --> [].
collect([H|T]) --> [H], collect(T).
inbetween(List, A, B, Result) :- phrase(betwixt(A, B, Result), List).
本例中的 DCG 很好地说明了正在发生的事情,结果与上述相同。为简洁起见,我也可以在第一个子句中使用 collect(_)
代替 anything
,但不想浪费未使用的参数。
要使用记入@false 的漂亮符号,我们可以使用 ...
作为术语,如下所示:
betwixt(A, B, M) --> ..., [A], collect(M), [B], ... .
... --> [].
... --> [_], ... .
collect([]) --> [].
collect([H|T]) --> [H], collect(T).