在Prolog中编写程序以查找每个X列表

4

我开始学习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
3个回答

5

除了其他人写的内容外,考虑使用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:在保留其声明属性的同时,最好的方法是使其尽可能确定。 - false
请参考我的这个问题 - false

1

你已经被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].

编辑 @false 消除了一个恶心的 bug:这里是一个修正,使用 if/then/else 结构。

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

1
你的程序在 occurences(a,[a,b,c,a],[a]). 的情况下出现了错误。因此,你的程序对于第三个参数不是稳定的。这是一个很好的例子,说明如何不要设置剪枝。 - false

0

考虑:

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) 中,你的定义是不完整的。 - false
哇,我不知道 OP 需要一个! - user206428
1
除此之外,还有什么方法可以知道你的定义是可靠的还是不可靠的? - false

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接