纯粹的Prolog程序以清晰的方式区分术语的平等和不平等,导致执行效率低下; 即使所有相关术语都是基础的.
关于SO的最近一个例子是这个答案.在此定义中,所有答案和所有失败都是正确的.考虑:
?- Es = [E1,E2], occurrences(E, Es, Fs).
Es = Fs, Fs = [E, E],
E1 = E2, E2 = E ;
Es = [E, E2],
E1 = E,
Fs = [E],
dif(E, E2) ;
Es = [E1, E],
E2 = E,
Fs = [E],
dif(E, E1) ;
Es = [E1, E2],
Fs = [],
dif(E, E1),
dif(E, E2).
Run Code Online (Sandbox Code Playgroud)
虽然程序从声明的角度来看是完美无缺的,但它在B,SICStus,SWI,YAP等当前系统上的直接执行效率却不必要地低效.对于以下目标,为列表的每个元素保留一个选择点.
?- occurrences(a,[a,a,a,a,a],M). M = [a, a, a, a, a] ; false. …
different(Xs, Ys) :-
member(X, Xs),
non_member(X, Ys).
different(Xs, Ys) :-
member(Y, Ys),
non_member(Y, Xs).
Run Code Online (Sandbox Code Playgroud)
虽然这个定义使用member/2和non_member/2几乎是1从声明的观点完美的,它产生于特定查询的冗余解决方案,并选择留点周围.
什么是改进的定义(以纯粹的方式可能使用if_/3和(=)/3),使得完全相同的解决方案集被描述different/2但至少对于地面查询是确定的(因此不会留下任何无用的选择点)并且省略(如有可能)任何多余的答案?
1
实际上,different([a|nonlist],[]), different([],[b|nonlist])成功了.它同样可能失败.所以两者都失败的解决方案很好(甚至可能更精细).
我目前正在开发一个关于Prolog的非常短的项目,并且试图将我创建的"过滤器"应用到列表中.我有你可以称之为过滤器的东西,但我无法应用它.如果我说明一下会更好:
filter(A, B)
Run Code Online (Sandbox Code Playgroud)
...如果满足某些条件,则输出'true'.
filterList(A, [X, Y, Z])
Run Code Online (Sandbox Code Playgroud)
...输出一个列表,其中包含第二个参数中使过滤器输出为false的所有元素.(因此,如果过滤器(A,X)为真,则输出为[Y,Z]).
我已准备好"过滤器"功能,但现在我需要将它应用于第二个示例中所示的列表,排除在应用第一个参数时过滤器返回true的所有元素.
因此,如果过滤器是简单的A == B,则该函数应该接收A [A,B,A,C,D,A]并输出[B,C,D],删除了所有元素显然,过滤器适用.
我在功能的基本结构方面遇到了麻烦,所以如果有人能为这样的功能提供一个基本的轮廓,那将会有很大的帮助.我尽可能地简化了我的情况,所以我可以拿出你能提供的任何东西,并根据我的需要进行修改.
提前致谢!
我正在解析一个由一系列行组成的相当简单的文件格式,每行都有一些空格分隔的字段,如下所示:
l 0x9823 1
s 0x1111 3
l 0x1111 12
?
Run Code Online (Sandbox Code Playgroud)
我正在使用SWI-Prolog.这是我到目前为止的DCG:
:- consult(library(pure_input)).
load_trace(Filename, Traces) :-
phrase_from_file(trace_file_phrase(Traces), Filename).
trace_file_phrase([]) --> [].
trace_file_phrase([T|Ts]) --> trace_phrase(T), trace_file_phrase(Ts).
trace_phrase(access(Type, Address, SinceLast)) -->
access_type(Type), space,
address(Address), space,
nat(SinceLast), newline.
access_type(load) --> "l".
access_type(store) --> "s".
address(Number) --> "0x", hexnum(Number).
hexdigit(N) --> digit(N).
hexdigit(10) --> "a". hexdigit(11) --> "b". hexdigit(12) --> "c".
hexdigit(13) --> "d". hexdigit(14) --> "e". hexdigit(15) --> "f".
hexnum(N) --> hexdigit(D), hexnum(D, N).
hexnum(N, N) --> [].
hexnum(A, N) --> hexdigit(D), …Run Code Online (Sandbox Code Playgroud) 我试图找出一种方法来检查两个列表是否相等,无论它们的元素顺序如何.
我的第一次尝试是:
areq([],[]).
areq([],[_|_]).
areq([H1|T1], L):- member(H1, L), areq(T1, L).
Run Code Online (Sandbox Code Playgroud)
但是,这只检查左侧列表中的所有元素是否都存在于右侧列表中; 意思areq([1,2,3],[1,2,3,4]) => true.在这一点上,我需要找到一种能够以双向意义测试事物的方法.我的第二次尝试如下:
areq([],[]).
areq([],[_|_]).
areq([H1|T1], L):- member(H1, L), areq(T1, L), append([H1], T1, U), areq(U, L).
Run Code Online (Sandbox Code Playgroud)
在哪里我会尝试重建左边的那个以及最后的交换列表; 但这次失败了.
我对递归的感觉非常差,根本不知道如何改进它,尤其是Prolog.任何提示或建议都将在此时受到赞赏.
我想编写一个函数,通过删除小于或等于特定数字的所有内容来过滤数字列表.该功能将采用两个参数:数字列表和要过滤的数字.该函数应返回一个列表,其中所有数字都大于过滤器编号.
有时这样:
filter_num_list(L1,N,L2) :- ...
test_filter_num_list :- filter_num_list([1,2,3,4,5,6,7,8,9],5,[5,6,7,8,9]).
Run Code Online (Sandbox Code Playgroud) removeAll(X, [ X | T], [ H1 | T1 ] ):-
( member ( X , T )
-> removeAll ( X , T , [ H1 | T1 ] )
;[ H1 | T1 ] is T
).
removeAll ( X , [ H | T ] , L ):-
removeAll ( X , T , L2 ), append ( [ H ] , L2 , L ).
Run Code Online (Sandbox Code Playgroud)
如果我通过“ removeAll(2,[1,1,2],L).”,
它会给出错误“ ERROR: is/2: Type error: 'evaluable' expected, found …
例子
divisible([L1],X) :-
L1 mod X =:= 0.
Run Code Online (Sandbox Code Playgroud)
询问
divisible([4,6,8,7],2).
Run Code Online (Sandbox Code Playgroud)
回复
[4,6,8]
Run Code Online (Sandbox Code Playgroud)
有什么指导吗?