【问题标题】:Program to find every list of X in Prolog在 Prolog 中查找每个 X 列表的程序
【发布时间】:2012-12-01 18:01:10
【问题描述】:

我开始学习 Prolog。这个程序试图获取给定元素的所有出现:

occurences(_, [], Res):- Res is [].
occurences(X, [X|T], Res):- 
    occurences(X,T,TMP),
    Res is [X,TMP].
occurences(X, [_|T], Res):- occurences(X,T,Res).

但这是错误:

?- occurences(a,[a,b,c,a],Res).
ERROR: is/2: Arithmetic: `[]/0' is not a function
^  Exception: (11) _G525 is [] ? creep
   Exception: (10) occurences(a, [], _G524) ? creep
   Exception: (9) occurences(a, [a], _G524) ? creep
   Exception: (8) occurences(a, [c, a], _G524) ? creep
   Exception: (7) occurences(a, [b, c, a], _G524) ? creep
   Exception: (6) occurences(a, [a, b, c, a], _G400) ? creep

【问题讨论】:

    标签: recursion prolog runtime-error prolog-dif


    【解决方案1】:

    除了其他人写的,考虑使用 dif/2 约束:

    occurrences(_, [], []).
    occurrences(X, [X|Ls], [X|Rest]) :-
            occurrences(X, Ls, Rest).
    occurrences(X, [L|Ls], Rest) :-
            dif(X, L),
            occurrences(X, Ls, Rest).
    

    您现在可以全方位使用谓词,例如:

    ?- occurrences(X, [a,a,b], Os).
    X = a,
    Os = [a, a] ;
    X = b,
    Os = [b] ;
    Os = [],
    dif(X, b),
    dif(X, a),
    dif(X, a) ;
    false.
    

    最后一个解决方案意味着如果 X 与 ab 都不同,则出现的列表为空。

    【讨论】:

    • +1:在保持其声明性属性的同时使其尽可能确定的最佳方法是什么?
    【解决方案2】:

    Rubens 已经告知您您的错误。我只是添加一个样式注释:通常在 Prolog 中,最好直接在头参数中编码模式:

    occurences(_, [], []).
    occurences(X, [X|T], [X|TMP]) :- 
        occurences(X,T,TMP), !.
    occurences(X, [_|T], Res) :-
        occurences(X,T,Res).
    

    我将第二个子句“输出”从 [X,TMP] 更正为 [X|TMP],并注意删减:没有它,程序产生的结果比要求的要多:

    ?- occurences(a,[a,b,c,a],Res).
    Res = [a, a] ;
    Res = [a] ;
    Res = [a] ;
    Res = [] ;
    false.
    

    剪裁:

    ?- occurences(a,[a,b,c,a],Res).
    Res = [a, a].
    

    edit @false 破坏了一个讨厌的错误:这里是一个更正,使用 if/then/else 构造

    occurences(_, [], []).
    occurences(X, [Y|T], Os) :-
        (   X = Y
        ->  Os = [X|R]
        ;   Os = R
        ),
        occurences(X,T,R).
    

    【讨论】:

    • 你的程序对occurences(a,[a,b,c,a],[a]). 错误地成功了所以你的程序对于第三个参数并不坚定。这是一个很好的例子,如何设置切割。
    【解决方案3】:

    考虑:

    occurrences(_, [], []) :- !.
    occurrences(X, [Y|L], R) :-
        X \== Y, !,
        occurrences(X, L, R).
    occurrences(X, [Y|L], [Y|R]) :-
        occurrences(X, L, R).
    

    测试:

    ?- occurrences(a,[a,b,a,c],O).
    O = [a, a].
    
    ?- occurrences(a,[a,X,a,c],O).
    O = [a, a].
    
    ?- occurrences(a,[a,X,a,c],[a]).
    false.
    
    ?- occurrences(a,[a,X,a,c],[a,a]).
    true.
    

    【讨论】:

    • 您的定义缺少模式声明或任何说明何时有效和何时无效的内容。例如。对于occurences(E,Xs,Ys),您的定义不完整。
    • 哇,我不知道 OP 需要一个!
    • 别人怎么知道你的定义什么时候可靠,什么时候不可靠?
    猜你喜欢
    • 2017-03-26
    • 1970-01-01
    • 1970-01-01
    • 2011-08-17
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    • 2015-02-24
    • 2013-11-16
    相关资源
    最近更新 更多