List 在SWI-prolog中实现nth1列表操作

List 在SWI-prolog中实现nth1列表操作,list,prolog,predicate,List,Prolog,Predicate,您将如何在Prolog中编写自己的谓词,以完全实现nth1函数的功能 对于那些不熟悉该功能的人,最好通过一个示例来显示其功能: ?-nth1(2[a,b,c],E,R) E=b R=[a,c] 调用并传递nth1函数时,将执行以下操作: -要从列表中删除的元素的索引(注意,它不是零索引,这里我们传递的是索引2) -列表(在本例中,它是[a,b,c]) -E,将为其分配从列表中删除的元素 -一个新的列表,它将保存新的列表,减去被删除的元素 我不知该如何开始。如有任何建议,将不胜感激。我知道在SWI

您将如何在Prolog中编写自己的谓词,以完全实现nth1函数的功能

对于那些不熟悉该功能的人,最好通过一个示例来显示其功能:

?-nth1(2[a,b,c],E,R)

E=b

R=[a,c]

调用并传递nth1函数时,将执行以下操作: -要从列表中删除的元素的索引(注意,它不是零索引,这里我们传递的是索引2) -列表(在本例中,它是[a,b,c]) -E,将为其分配从列表中删除的元素 -一个新的列表,它将保存新的列表,减去被删除的元素

我不知该如何开始。如有任何建议,将不胜感激。我知道在SWI Prolog中使用3或4行递归应该是可行的,我只是不知道从哪里开始。

这基本上可以给你答案。为了让你开始,考虑你的基本情况,应该是

 nth1(1, [E|R], E, R).

现在,你如何通过递归这个想法来编写其他案例?实际上,这只是掌握Prolog列表语法的窍门。

建议在swi Prolog实现源代码中搜索nth1,网址为:


棘手的是,您必须生成或返回nth1项,这取决于您传入的未绑定变量。。所以在几行代码中可能不可能做到这一点。

@EMS的答案相当不错,但正确实现该谓词可能很棘手。我们必须考虑在NTH1/4关系上有意义的每个实例化模式,因为问题需要完全相同的构建行为。因此,nth1还可以搜索元素并在位置处插入

SWI Prolog用于在不同实现之间进行效率切换,但应该可以在需要时对关系建模,以测试实例化

我称之为mth1而不是nth1

mth1(1, [X|R], X, R).
mth1(_, L, _, _) :-
    L == [],  % (==)/2 fails when L is a var
    !, fail.
mth1(P, [H|T], X, [H|R]) :-
    (  var(P)  % are we searching the position?
    -> mth1(Q, T, X, R),
       P is Q + 1
    ;  Q is P - 1,
       mth1(Q, T, X, R)
    ).
插入时需要测试
L=[]

当然,调试是必需的,下面是一些简单的测试:

?- mth1(2,[a,b,c,d,e],X,Y).
X = b,
Y = [a, c, d, e] ;
false.

?- mth1(X,[a,b,c,d,e],b,Y).
X = 2,
Y = [a, c, d, e] ;
false.

?- mth1(2,X,b,[a,c,d,e]).
X = [a, b, c, d, e] ;
false.
您应该检查是否涵盖了SWI Prolog允许的所有实例化模式

如何执行这个简单的实现?这里有一个基本的测试

test_performance(N) :-
    numlist(1, N, L),
    time(test_performance(L, N, nth1)),
    time(test_performance(L, N, mth1)).

test_performance(L, N, P) :-
    writeln(P),
    writeln('access last'),
    time((call(P, N, L, X, _), assertion(X == N))),
    writeln('find position of last'),
    time((call(P, Z, L, N, _), assertion(Z == N))),
    writeln('add tail'),
    time(call(P, N, _, tail, L)).
令我惊讶的是,窥视元素和添加尾部的速度(稍微)更快,而查找位置的速度则慢得多(因为缺少尾部递归?)

事实上,对于较长的列表,职位搜索显示出其效率低下,典型的StackOverflow:

?- test_performance(2000000).
nth1
access last
% 2,000,011 inferences, 1,218 CPU in 1,221 seconds (100% CPU, 1641399 Lips)
find position of last
% 2,000,003 inferences, 1,327 CPU in 1,330 seconds (100% CPU, 1507572 Lips)
add tail
% 2,000,009 inferences, 0,958 CPU in 0,960 seconds (100% CPU, 2088038 Lips)
% 6,000,243 inferences, 3,504 CPU in 3,511 seconds (100% CPU, 1712549 Lips)
mth1
access last
% 2,000,002 inferences, 1,116 CPU in 1,118 seconds (100% CPU, 1792625 Lips)
find position of last
% 1,973,658 inferences, 2,479 CPU in 2,485 seconds (100% CPU, 796219 Lips)
% 3,973,811 inferences, 3,595 CPU in 3,603 seconds (100% CPU, 1105378 Lips)
ERROR: Out of local stack

首先,将问题分解为更小的组成部分。从列表中选择第n项很容易。收集的差别就不那么大了

因此,将其分为两部分:

  • 首先,将列表分成前缀、所需项和后缀

  • 接下来,通过
    append/3
    连接前缀和后缀以形成余数列表

因此,您的
my\u nth1\4
谓词应该如下所示:

nth1( N , List , Nth, Rest ) :-
  burst( N , List , Pfx , Nth , Sfx ) ,
  append( Pfx , Sfx , Rest )
  .

% ------------------------------------------------------------------------------
% burst a list into 3 parts - a prefix, an item and a suffix
% based on the specified offset N (where 0 indicates the first item of the list)
%
% The prefix is built up using a "difference list" as we recurse down looking
% for the Nth item.
% ------------------------------------------------------------------------------
burst( 0 , [L|Ls] , []      , L   , Ls  ).
burst( N , [L|Ls] , [L|Pfx] , Nth , Sfx ) :- 
  N > 0 ,
  N1 is N - 1 ,
  burst( N1 , Ls , Pfx , Nth , Sfx )
  .

根据问题的性质和原始海报的处理方式,标记为家庭作业(Carleton U)
nth1( N , List , Nth, Rest ) :-
  burst( N , List , Pfx , Nth , Sfx ) ,
  append( Pfx , Sfx , Rest )
  .

% ------------------------------------------------------------------------------
% burst a list into 3 parts - a prefix, an item and a suffix
% based on the specified offset N (where 0 indicates the first item of the list)
%
% The prefix is built up using a "difference list" as we recurse down looking
% for the Nth item.
% ------------------------------------------------------------------------------
burst( 0 , [L|Ls] , []      , L   , Ls  ).
burst( N , [L|Ls] , [L|Pfx] , Nth , Sfx ) :- 
  N > 0 ,
  N1 is N - 1 ,
  burst( N1 , Ls , Pfx , Nth , Sfx )
  .