我是Prolog的新手,我遇到了一些来自OOP的困难。我需要递归地运行一些角色,但要记住我经历过的事情。在OOP中,我只想创建一个数组或arraylist来跟踪我使用过的任何内容。但是,我似乎无法在Prolog中找到类似的方法。我如何检查我已经使用过的东西。
确切的问题是我想要运行一组字符并停止,如果我基本上两次来到同一个。我的想法是将每一个添加到列表中并检查下一个是否是列表的成员。
感谢任何帮助
谢谢
答案 0 :(得分:2)
以下是基于@鲍里斯的回答;您也可以使用目标maplist(dif(X),Seen)
代替\+ memberchk(X,Seen)
来保留logical-purity:
foo([],_). % 1 foo([X|Xs],Seen) :- % 2 maplist(dif(X),Seen), % 3 foo(Xs,[X|Seen]). % 4
答案 1 :(得分:1)
最基本的实施:
foo([], _). % 1
foo([X|Xs], Seen) :- % 2
\+ memberchk(X, Seen), % 3
foo(Xs, [X|Seen]). % 4
\+ X
代表"当X失败时成功"),将元素添加到所见元素列表中并检查列表的其余部分(4)。但是我认为这不是你应该写的东西吗?由于目前尚不清楚您的最终目标是什么,因此很难提出更好的解决方案。
一些提示:
答案 2 :(得分:0)
你可能会觉得这很有用:Prolog iterating over list本质上,Prolog没有迭代,但确实有递归。您需要通过列表递归来完成您要执行的操作。
答案 3 :(得分:0)
我认为问题是如何找到以第一个重复元素开头的列表的后缀。如果我是正确的,那么实现可以是以下几行:找到一个重复的元素并用于返回所需后缀或失败的谓词,如果没有重复,则后缀为空。假设第一个参数是一个没有自由变量的正确闭合列表的实现可以是
stop([],[]).
stop([X|R],Rr) :-
stop_at(R,X,Rr), !.
stop([_|R],Rr) :-
stop(R,Rr).
stop_at([X|R],X,[X|R]) :- !.
stop_at([_|R],X,Rr) :-
stop_at(R,X,Rr).
样品运行:
?- stop([a,b,c],R).
R = [] ? ;
no
?- stop([a,b,c,d,a,e,a,e],R).
R = [a,e,a,e] ? ;
no
?- stop([b,c,d,c,e],R).
R = [c,e] ? ;
no
答案 4 :(得分:0)
将每个找到的字符添加到列表中,然后使用此列表检查是否有两次字符将与找到的字符列表的大小成线性关系。这可能是也可能是不可接受的w.r.t.性能。你有多少个不同的角色?只有ASCII可打印字符?完整的Unicode?由于只有一些Prolog系统提供了数组,因此您获得比列表更好的性能的最佳选择是二叉搜索树,它将在平均情况下为您提供O(log(n))。但你可以做得更好。在标记问题View header = getLayoutInflater().inflate(R.layout.non_sticky_header, null);
list.addHeaderView(header);
时,您可以使用此系统读取黑树库(继承自YAP)。在最坏的情况下,这也应该为您提供O(log(n))。使用这个库(作为在其他答案中使用列表的替代方法),你可以写一些东西:
swi-prolog
这是否是使用列表的有价值(性能方面)替代方案?你没有提供足够的细节来回答这个问题。最好运行一些测试。另外值得注意的是,列表中的插入是O(1)(当您执行:- use_module(library(rbtrees)).
foo(List) :-
rb_new(Seen),
foo(List, Seen).
foo([], _).
foo([Head| Tail], Seen) :-
( rb_lookup(Head, _, Seen) ->
true
; rb_insert(Seen, Head, _, Seen2),
foo(Tail, Seen2)
).
+ Head
- > List
时),但在红黑树中插入是O(log( n))的