列表 - 计算与前一个术语相关的原子

时间:2016-05-03 14:47:11

标签: list prolog

我想计算列表中与后面的元素有关系的元素数。 我通过使用累加器变量工作的谓词,如果谓词相关返回true,它会递增。 以下示例代码用于检查元素大于其上一个元素的次数。

所以例如

"0000"

应该返回3.

代码几乎可以工作。它正确递增累加器变量。但是,当函数尝试将末尾的最后2个与不存在的下一个术语进行比较时,该函数返回false。

count_list([1,2,3,2,1,3,2],Count).

有没有人对如何创建优雅的终止条件有任何建议,以便我可以返回累计值?

3 个答案:

答案 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系统支持,您可以这样继续:

:- use_module(library(clpfd)).
:- use_module(library(lists), [last/3]).
:- use_module(library(maplist), [maplist/4]).

要关联相邻的项目,请查看[E|Es]EsFs的两个子列表。如果,比方说, [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/4i0_i1_gt01/3将相应的列表项列在FsEs0 / 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)可以提供更多功能。