例如,如果我有一个列表[1,1,2,3,5,1]
,我想计算此列表中1的数量,我该怎么做?
count([], 0).
count([H|T], N) :-
count(T, X),
( H =:= 1
-> N is X+1
; N is X
),
N > 0.
在这个递归中,如果Head等于1,我想做,然后计数+ 1,如果Head不是1,那么计数保持不变。但是,如果列表中的值不是1,则返回false。我知道问题是,一旦元素不满足if语句,它就会失败;它永远无法达到else语句。我该如何解决?请帮忙!!!!
答案 0 :(得分:3)
替代解决方案,它使用foldl / 4并定义更高阶谓词(将另一个谓词作为参数的谓词):
count_step(Condition, Item, CurrentCount, NewCount) :-
call(Condition, Item) ->
NewCount is CurrentCount + 1 ;
NewCount = CurrentCount.
count(List, Condition, Count) :-
foldl(count_step(Condition), List, 0, Count).
is_one(Expr) :-
Expr =:= 1.
用法示例:
?- count([0, 2, 3, 0], is_one, Count).
Count = 0.
?- count([1, 2, 3, 1], is_one, Count).
Count = 2.
另一种(相当肮脏的)方法是使用include / 3和length / 2:
count(List, Condition, Count) :-
include(Condition, List, Filtered),
length(Filtered, Count).
答案 1 :(得分:3)
让我们从您的代码开始并询问一些问题!
我在旁边添加了评论,显示了我预期的结果......
?- count([0,2,3,0], Count).
false % bad: expected Count = 0
?- count([1,2,3,1], Count).
Count = 2 % ok
?- count([1,2,3], Count).
false % bad: expected Count = 1
如果我的期望与您的期望匹配,则代码的最小修复很少:只需移除目标N > 0
!
count([], 0).
count([H|T], N) :-
count(T, X),
( H =:= 1
-> N is X+1
; N is X
).
让我们再次运行查询:
?- count([0,2,3,0], Count).
Count = 0 % was “false”, now ok
?- count([1,2,3,1], Count).
Count = 2 % was ok, still is ok
?- count([1,2,3], Count).
Count = 1. % was “false”, now ok
底线:只要最后一个列表项不等于1,原始代码就会失败。
答案 2 :(得分:2)
试试这个:
count([],0).
count([1|T],N) :- count(T,N1), N is N1 + 1.
count([X|T],N) :- X \= 1, count(T,N).
答案 3 :(得分:2)
由于您已经选择使用(;)/ 2 - if-then-else,因此您可能会发现以下if_/3变体很有趣:
list_1s(L,X) :-
length(L,Len),
list_1s_(L,X,0,Len).
list_1s_([],X,X,0).
list_1s_([Y|Ys],X,Acc0,Len1) :-
if_(Y=1, Acc1 is Acc0+1, Acc1 is Acc0),
Len0 is Len1-1,
list_1s_(Ys,X,Acc1,Len0).
调用谓词list_1s / 2中的目标长度/ 2与实际关系list_1s_ / 4的第4个参数一起用于确保如果使用第一个参数调用谓词,则以公平的方式列出结果列表变数。 list_1s_ / 4的第三个参数是一个累加器,用于计算从零开始的1的数量,以使谓词尾递归。因此,如果列表为空,则list_1s_ / 4的第2和第3个参数相等。现在让我们看一些示例查询。在数字方向列表中,谓词产生了预期的结果并且确定性地成功(它不会使不必要的选择点打开,在单个答案后不需要按;
):
?- list_1s([],X).
X = 0.
?- list_1s([1,2,3],X).
X = 1.
?- list_1s([1,2,3,1],X).
X = 2.
?- list_1s([0,2,3,0],X).
X = 0.
在列出方向的数字中,对于任何给定的数字,有无限多的列表,并且如上所述,它们以公平的方式列出,即,在移动到长度n之前列出长度为n的列表的所有可能性1:
?- list_1s(L,0).
L = [] ; % <- empty list
L = [_G386], % <- length 1
dif(_G386, 1) ;
L = [_G442, _G445], % <- length 2
dif(_G442, 1),
dif(_G445, 1) ;
L = [_G498, _G501, _G504], % <- length 3
dif(_G498, 1),
dif(_G501, 1),
dif(_G504, 1) ;
.
.
.
?- list_1s(L,1).
L = [1] ; % <- length 1
L = [1, _G404], % <- length 2
dif(_G404, 1) ;
L = [_G401, 1], % <- length 2
dif(_G401, 1) ;
L = [1, _G460, _G463], % <- length 3
dif(_G460, 1),
dif(_G463, 1) ;
L = [_G457, 1, _G463], % <- length 3
dif(_G457, 1),
dif(_G463, 1) ;
L = [_G457, _G460, 1], % <- length 3
dif(_G457, 1),
dif(_G460, 1) ;
.
.
.
最常见的查询是以公平的方式列出结果:
?- list_1s(L,X).
L = [], % <- empty list
X = 0 ;
L = [1], % <- length 1
X = 1 ;
L = [_G413], % <- length 1
X = 0,
dif(_G413, 1) ;
L = [1, 1], % <- length 2
X = 2 ;
L = [1, _G431], % <- length 2
X = 1,
dif(_G431, 1) ;
L = [_G428, 1], % <- length 2
X = 1,
dif(_G428, 1) ;
.
.
.