counter([],[]).
counter([H|T],[[H,C1]|R]) :- counter(T,[[H,C]|R]),!, C1 is C+1.
counter([H|T],[[H,1]|R]) :- counter(T,R).
“!”的影响是什么?因为我在上面和下面的代码中输入相同的输出?
counter([],[]).
counter([H|T],[[H,C1]|R]) :- counter(T,[[H,C]|R]),C1 is C+1.
counter([H|T],[[H,1]|R]) :- counter(T,R).
我是Prolog的新手。
答案 0 :(得分:4)
这是我纯粹而有希望的高效解决方案:
counter([X|L], C):- counter(L, X, 1, C).
counter([],X, Cnt, [[X,Cnt]]).
counter([Y|L], X, Cnt, [[X,Cnt]|C]):-
dif(X, Y),
counter(L, Y, 1, C).
counter([X|L],X, Cnt, [[X,XCnt]|C]):-
Cnt1 #= Cnt+1,
Cnt1 #=< XCnt,
counter(L, X, Cnt1, [[X,XCnt]|C]).
根据@false:
的建议使用if_3
counter([X|L], C):- counter(L, X, 1, C).
counter([],X, Cnt, [[X,Cnt]]).
counter([Y|L], X, Cnt, [[X,XCnt]|C]):-
if_(X=Y,
(
Cnt1 #= Cnt+1,
Cnt1 #=< XCnt,
counter(L, X, Cnt1, [[X,XCnt]|C])
),
(
XCnt=Cnt,
counter(L, Y, 1, C)
)
).
答案 1 :(得分:3)
剪切运算符!
通过修剪所有选择点来提交当前的派生路径。鉴于一些事实
fact(a).
fact(b).
你可以比较有和没有剪切的答案:
?- fact(X).
X = a ;
X = b.
?- fact(X), !.
X = a.
如您所见,通用查询现在仅报告其首次成功。仍然是查询
?- fact(b), !.
true.
成功。这意味着,该切割违反了,
对逻辑连接的解释:
?- X = b, fact(X), !.
X = b.
?- fact(X), !, X=b.
false.
但是根据我们对连词的理解,A∧B应该在B∧A成立时准确保持。那为什么要这样呢?
效率:可以使用剪切,这样它们只会更改执行属性,而不会更改谓词的答案。这些所谓的绿色削减例如在Richard O'Keefe的Craft of Prolog中描述。如上所述,保持带切割的谓词的正确性比没有切口的正确性要困难得多,但显然,正确性应该在效率之前。
看起来您的问题是绿色的,但如果答案没有变化,我不能100%确定。
否定:根据closed world assumption的逻辑否定用cut表示。您可以将neg(X)定义为:
neg(X) :-
call(X),
!,
false.
neg(_) :-
true.
因此,如果call(X)
成功,我们就会删除第二条规则的选择点并导出false。否则,什么都没有削减,我们得出真实。请注意,这不是经典逻辑中的否定,并且它受到切割的非逻辑效应的影响。假设您将谓词land/1
定义为大陆之一:
land(africa).
land(america).
land(antarctica).
land(asia).
land(australia).
land(europe).
然后将水定义为不在陆地上的所有东西:
water(X) :-
neg(land(X)).
然后你可以正确获得:
?- water(pacific).
true.
?- water(africa).
false.
但你也可以得出:
?- water(space).
true.
哪个不应该成立。特别是在经典逻辑中:
land(africa) ∧
land(america) ∧
land(antarctica) ∧
land(asia) ∧
land(australia) ∧
land(europe) → ¬ land(space).
无效。同样,如果你在Prolog中使用否定,你应该清楚自己在做什么。
答案 2 :(得分:3)
以下是我尝试使用if_/3
:
counter([], []).
counter([H|T], [[H,C]|OutT] ):-
if_(
T=[],
(C = 1,OutT=[]),
(
[H|T] = [H,H1|T2],
if_(
H=H1,
(counter([H1|T2], [[H1,C1]|OutT]), C is C1+1),
(C = 1, counter([H1|T2], OutT))
)
)
).