【问题标题】:Error counting occurrences in a list in PrologProlog 列表中的错误计数
【发布时间】:2017-05-22 09:43:37
【问题描述】:

我试图在 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 的值。

【问题讨论】:

    标签: prolog


    【解决方案1】:

    如果您坚持打印该消息,我建议至少将输出与描述实际关系的谓词分开。考虑一下这种模式:

    calling_predicate(...) :-
       other_predicate(...),   % <- predicate describing the actual relation
       format(...).            % <- output
    

    例如,您可以将count_occur/3 替换为calling_predicate,并将@User9213 的帖子中的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).
    

    由于列表中的元素不一定是数字,因此最好对参数 X 使用转义序列 ~w 而不是 ~d(有关详细信息,请参阅 format/2 的文档)。如果您使用给定的示例进行查询,您会得到所需的结果:

    ?- count_occur(5,[2,5,5,5,6,6,8,9,9,9], N).
    Element 5 occurs 3 times. 
    N = 3.
    

    请注意,此查询确定性地成功。也就是说,没有多余的选择点,因此在 Prolog 告诉您唯一答案后,您无需输入;。 cmets 中 @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).
    

    【讨论】:

    • 我要试试。我正在研究其他替代方法,用 2 个参数编写辅助谓词。正如我提到的,我从序言开始。感谢您的帮助,非常感谢。
    【解决方案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).
    

    【讨论】:

    • 我会试试你的解决方案。在我的解决方案中,我们得到了我想要的消息,但查询的第三个参数(计数)必须为 0。
    【解决方案3】:

    我发现了错误。解决办法是:

    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 语句错误,没有充分增加。

    【讨论】:

    • 这仍然不是解决方案。例如:?- count_occur(X, [a,b,c], N). 甚至?- count_occur(a, [a,b,c], N). 理想情况下,我们可以在多个方向上使用关系,而不仅仅是在非常具体的特殊情况下。例如,您可以通过使用 dif/2 和 CLP(FD) 约束 (#=)/2 而不是 (is)/2 来实现这种通用性。
    • 我的目的是显示Element 5 occurrs 3 times.,并且我收到了带有此代码的此消息。但是,你是对的,我会试试的。谢谢。
    • 您可能还想查看查询count_occur(1,[2,X],0).length(Xs,_), count_occur(1,[1|Xs],0). 的(不完整)结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-05
    • 1970-01-01
    相关资源
    最近更新 更多