我试图在Prolog中开发一个小程序。目前,我从Prolog开始,因此有些问题我不太了解。
我的程序假装计算列表中元素的出现次数。最后,它必须显示下一条消息:"元素X出现N次。"
代码如下:
count_occur(X, [], N) :- format("Element ~d occurrs ~d times. ~n", [X,N]).
count_occur(X, [X|T], N) :-
count_occur(X, T, N2),
N is N2 + 1.
count_occur(X, [Y|T], N) :-
X \= Y,
count_occur(X, T, N).
咨询一个例子我总是得到以下错误:
?- count_occur(5,[2, 5, 5, 5, 6, 6, 8, 9, 9, 9], 0).
Element 5 ocurrs
ERROR: Arguments are not sufficiently instantiated
ERROR: In:
ERROR: [19] format("Element ~d ocurrs ~d times. ~n",[5,_8398])
ERROR: [18] count_occur(5,[],_8428) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:1
ERROR: [11] count_occur(5,[5,6|...],_8456) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:3
ERROR: [10] count_occur(5,[5,5|...],_8496) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:3
ERROR: [9] count_occur(5,[5,5|...],0) at /Users/serrodcal/Repositories/PLExercises1/ex1.pl:3
ERROR: [7] <user>
ERROR:
ERROR: Note: some frames are missing due to last-call optimization.
ERROR: Re-run your program in debug mode (:- debug.) to get more detail.
我正在使用像计数器这样的第三个参数,但在案例基础上Prolog不知道N的值。
答案 0 :(得分:3)
如果您坚持打印该消息,我建议至少将输出与描述实际关系的谓词分开。考虑一下这种模式:
calling_predicate(...) :-
other_predicate(...), % <- predicate describing the actual relation
format(...). % <- output
例如,您可以将count_occur/3
替换为来自@ User9213帖子的calling_predicate
和count_occur_/3
other_predicate
。或者,您可以选择使用@mat建议的CLP(FD)。例如,考虑使用if_/3的以下版本:
:- use_module(library(clpfd)).
count_occur(X, L, N) :-
list_x_count_(L,X,N,0), % <- actual relation
format("Element ~w occurs ~d times. ~n", [X,N]). % <- output
list_x_count_([],_X,N,N).
list_x_count_([Y|Ys],X,N,N0) :-
if_(Y=X,(N0 #< N, N1 #= N0+1), N1 #= N0),
list_x_count_(Ys,X,N,N1).
由于列表中的元素不一定是数字,因此对于参数~w
而不是X
使用转义序列~d
是恰当的(参见{{3}的文档更多细节)。如果您使用给定的示例查询,则会得到所需的结果:
?- count_occur(5,[2,5,5,5,6,6,8,9,9,9], N).
Element 5 occurs 3 times.
N = 3.
请注意,此查询会确定性地成功。也就是说,没有多余的选择点,因此在Prolog告诉您唯一答案后,您无需输入;
。 @mat和@ lambda.xy.x在评论中提供的示例查询也起作用:
?- count_occur(1,[2,X],0).
Element 1 occurs 0 times.
dif(X, 1).
?- count_occur(a, [a,b,c], N).
Element a occurs 1 times.
N = 1.
?- count_occur(X, [a,b,c], N).
Element a occurs 1 times.
X = a,
N = 1 ;
Element b occurs 1 times.
X = b,
N = 1 ;
Element c occurs 1 times.
X = c,
N = 1 ;
Element _G210 occurs 0 times.
N = 0,
dif(X, c),
dif(X, b),
dif(X, a).
答案 1 :(得分:2)
我不知道它是如何工作的,就像你写的那样。也许这样写:
count_occur(X, L, N) :- count_occur_(L, X, N).
count_occur_([], _, 0). % the 0 here is important (why?)
count_occur_([X|Xs], X, N) :-
count_occur_(Xs, X, N0),
succ(N0, N).
count_occur_([Y|Ys], X, N) :-
dif(Y, X),
count_occur_(Ys, X, N).
答案 2 :(得分:-1)
我发现了错误。解决方案是:
count_occur(X, [], N) :- format("Element ~d occurrs ~d times. ~n", [X,N]).
count_occur(X, [X|T], N) :-
N2 is N + 1,
count_occur(X, T, N2).
count_occur(X, [Y|T], N) :-
X \= Y,
count_occur(X, T, N).
第二次count_occur语句错误,并且没有充分递增。