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).