使用SWI Prolog,有一个谓词可以找到名为nth1的列表中的第n个项目。我想实现我自己的谓词版本,但是如果您查看列表(第nth1)代码,SWI会非常复杂。有没有更简单的方法呢?Prolog中的简单nth1谓词
谢谢:)。
使用SWI Prolog,有一个谓词可以找到名为nth1的列表中的第n个项目。我想实现我自己的谓词版本,但是如果您查看列表(第nth1)代码,SWI会非常复杂。有没有更简单的方法呢?Prolog中的简单nth1谓词
谢谢:)。
的SWI代码是有点复杂,因为谓词可以用来从一个变量指标产生:
?- nth1(Idx,[a,b,c],X).
Idx = 1,
X = a ;
Idx = 2,
X = b ;
Idx = 3,
X = c ;
false.
如果你不希望这样的行为,nth1/3
可以很容易地在nth0
方面实现的:
nth1(Idx,List,X) :-
Idx0 is Idx-1,
nth0(Idx0,List,X).
编辑:它也可以在短短的几行代码,而不nth0
做:
nth1(1,[X|_],X) :- !.
nth1(Idx,[_|List],X) :-
Idx > 1,
Idx1 is Idx-1,
nth1(Idx1,List,X).
谢谢larsmans,我不想使用任何第n个谓词,我已经发布了我的解决方案,您怎么看?感谢这篇文章。 – ale 2010-11-21 12:35:36
@shuyin,我也发布了一个'nnth0'的解决方案。 – 2010-11-21 14:40:45
我不是故意矛盾或者让别人来做我的工作,我只是想要一些建议,抱歉不清楚。
我已经自己实现它,但你们可能会建议改进或更好的方法吗?我经常在Prolog中发现自己正在写一个谓词,用一个计数器或一组计数器来得到一个谓词,用较少的参数来调用具有额外参数的子句。这通常会导致生成相当多的代码。无论如何,这是我刚才的实现:
item_at(N, L, Item) :-
item_at(N, 0, L, Item).
item_at(N, Count, [H|_], Item) :-
CountNew is Count + 1,
CountNew = N,
Item = H.
item_at(N, Count, [_|T], Item) :-
CountNew is Count + 1,
item_at(N, CountNew, T, Item).
有什么意见?谢谢 :)。用法:
?- item_at(3,[a,b,c,d,e],Item).
Item = c ;
+1,这个版本是相当一般的(尽管它可能会在回溯/生成时进入无限递归)。一个建议,第二个条款可以更短:'item_at(N,Count,[H | _],H): - N是Count +1 1. – 2010-11-21 14:44:15
谢谢larsmans,这是一个很好的改进,非常感谢: )。测试和工作,我可以看到如何:)。 – ale 2010-11-21 15:07:46
考虑使用有限域约束一般(可逆)整数运算:
:- use_module(library(clpfd)).
nth1(1, [E|_], E).
nth1(N, [_|Xs], E) :-
N #> 1,
N #= N1 + 1,
nth1(N1, Xs, E).
这与shuyin的解决方案有相同的无限递归问题,效率不高。 +1虽然优雅。 (但是,为了提高效率,我会添加一个约束'N#> 1',并且可能需要剪切。) – 2010-11-21 15:52:20
是的,将N#> 1添加到第二个子句中是个好主意,我认为这会消除无限递归意思是说,即对于像? - nth1(3,Es,X)这样的查询?但是,如果在第一个子句中添加一个剪切,将会消除有效的解决方案,例如对于最一般的查询? - nth1(N,Ls,E),从而使谓词不完整。 – mat 2010-11-21 17:08:12
你是对的。 – 2010-11-22 10:41:03
澄清你所说的“简单”?更少的代码行?您可以移除例如“列表:nth0_det(3,[_,_,_,A | _],A): - !。”否则,简单化的唯一方法是使其不那么一般。这是你想要的吗? – Kaarel 2010-11-21 20:57:02