我想计算列表中与后面的元素有关系的元素数。 我通过使用累加器变量工作的谓词,如果谓词相关返回true,它会递增。 以下示例代码用于检查元素大于其上一个元素的次数。
所以例如
"0000"
应该返回3.
代码几乎可以工作。它正确递增累加器变量。但是,当函数尝试将末尾的最后2个与不存在的下一个术语进行比较时,该函数返回false。
count_list([1,2,3,2,1,3,2],Count).
有没有人对如何创建优雅的终止条件有任何建议,以便我可以返回累计值?
答案 0 :(得分:4)
有没有人对如何创建优雅的终止条件有任何建议,以便我可以返回累计值?
您遇到的问题是您的查询失败。首先尝试尽可能减少查询。当然,你希望它适用于:
?- listofitems([], Count).
Count = 0.
然而,它已经失败了:
?- listofitems([1], Count).
false.
因此,让我们试着深入研究其原因。
由于您的程序是纯粹的(除write
之外),因此可以通过考虑程序的泛化来更好地诊断它。我更喜欢看这样的概括,因为我不想读太多(眼疲劳等):
:- op(950, fy, *). *_. listofitems([], N,N). listofitems([A,B|T], Acc,N) :- *( related(A,B) -> Acc1 is Acc+1 ; Acc1 = Acc ), *listofitems([B|T], Acc1,N). count_list(L,N):- listofitems(L,0,N). ?- count_list([1], Count). false.
即使这种概括也失败了!所以现在在绝望中我尝试询问最常见的查询。就像我问one thing after the other并在没有之后得到一个noe时那样。好这是Prolog,因为我们可以问:"说出你所知道的一切"。
?- count_list(Es,Count).
Es = [], Count = 0
; Es = [_,_|_].
所以只有空列表和列表的情况只有至少两个元素。但是对于一个单一的列表没有答案!因此,你必须以某种方式概括程序。
一种自然的方式是添加一个事实
listofitems([_], N, N).
作为一个小问题,这并不是一个终止条件"而是一个"基本案例"。
如果您真的想要跟踪代码,我建议these techniques而不是添加手动writes
。他们太容易出错。
答案 1 :(得分:4)
如果所有列表项都是整数且Prolog系统支持clpfd,您可以这样继续:
:- use_module(library(clpfd)). :- use_module(library(lists), [last/3]). :- use_module(library(maplist), [maplist/4]).
要关联相邻的项目,请查看[E|Es]
,Es
和Fs
的两个子列表。如果,比方说,
[E|Es] = [1,2,3,2,1,3,2]
持有......
Fs
缺少最后项(Fs = [1,2,3,2,1,3,2]
)...... Es
缺少第一个项(Es = [1,2,3,2,1,3,2]
)。 maplist/4
和i0_i1_gt01/3
将相应的列表项列在Fs
和Es
到0
/ 1
:
i_j_gt01(I, J, B) :- % if I #< J then B #= 1 I #< J #<=> B. % if I #>= J then B #= 0 ?- maplist(i_j_gt01, [1,2,3,2,1,3], [2,3,2,1,3,2], Bs). Bs = [1,1,0,0,1,0].
最后,使用[1,1,0,0,1,0]
总结sum/3
:
?- sum([1,1,0,0,1,0], #=, N).
N = 3.
让我们把它们放在一起!
count_adj_gt([E|Es], N) :- last(Fs, _, [E|Es]), % or: `append(Fs, [_], [E|Es])` % or: `list_butlast([E|Es], Fs)` maplist(i_j_gt01, Es, Fs, Bs), sum(Bs, #=, N).
使用SICStus Prolog 4.3.2的示例查询:
?- count_adj_gt([1,2,3,2,1,3,2], N).
N = 3. % succeeds deterministically
答案 2 :(得分:1)
不确定
优雅的终止条件
我的整个代码将是
?- Vs=[1,2,3,2,1,3,2], aggregate_all(count, (append(_,[X,Y|_], Vs), X<Y), Count).
这就是......
如果您需要更复杂的东西,请记住库(clpfd)可以提供更多功能。