二叉树prolog中的事件计数
我想实现一个代码,该代码将获取整个树中某个数字的出现次数,例如:二叉树prolog中的事件计数,prolog,binary-tree,Prolog,Binary Tree,我想实现一个代码,该代码将获取整个树中某个数字的出现次数,例如: numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil), bt(3, nil, nil)), bt(8, bt(7, nil, nil), bt(9, nil, nil))), N). N
numberOfOccurrences(7, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), N).
N = 1;
我该怎么做呢?你试过定义吗
出现次数(7,bt(6,bt(2,bt(1,无,无),
bt(3,无,无),,
英国电信(8,英国电信(7,无,无),
bt(9,零,零),1)。
??你试过定义吗
出现次数(7,bt(6,bt(2,bt(1,无,无),
bt(3,无,无),,
英国电信(8,英国电信(7,无,无),
bt(9,无,无)),N):-
N=1。
??你试过定义吗
出现次数(7,T,N):-
T=bt(6,bt(2,bt(1,无,无),
bt(3,无,无),,
英国电信(8,英国电信(7,无,无),
bt(9,无,无),,
N=1。
??甚至可能
出现次数(7,T,N):-
T=bt(6,TL,TR),
TL=bt(2,bt(1,无,无),%
bt(3,无,无),,
TR=bt(8,bt(7,无,无),%
bt(9,无,无),,
N=1。
??你也试过定义吗
出现次数(7,T,N):-
T=bt(6,TL,TR),
N1=0,%
TL=bt(2,bt(1,无,无),
bt(3,无,无),,
NL=0,%
TR=bt(8,bt(7,无,无),
bt(9,无,无),,
NR=1,%
N为N1+NL+NR.%
??难道不是这样吗
出现次数(7,T,N):-
T=bt(6,TL,TR),
N1=0,
TL=bt(2,bt(1,无,无),
bt(3,无,无),,
发生次数(7,TL,NL),%
NL=0,
TR=bt(8,bt(7,无,无),
bt(9,无,无),,
发生次数(7,TR,NR),%
NR=1,
N是N1+NL+NR。
??而且还只是
出现次数(7,T,N):-
T=bt(6,TL,TR),
N1=0,
%%
发生次数(7,TL,NL),
%%
发生次数(7次,TR,NR),
%%
N是N1+NL+NR。
??你有没有尝试过进一步推广它,去掉最后一个人为的具体值,也用逻辑变量替换它们
出现次数(X,T,N):-%
T=bt(Y,TL,TR),%
计数一次可能发生的事件(X,Y,N1),
发生次数(X、TL、NL),%
发生次数(X、TR、NR),%
N是N1+NL+NR。
??你能继续这样想吗?你应该试着把大问题分解成多个小问题。因此,首先:在树上操作是复杂的,列表更易于处理:
treeToList(Tree, List) :-
% I use an accumulator, starting with an empty list.
treeToList(Tree, [], List).
% The bottom is reached: The accumulated elements are the result.
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
Accu1 = [E|Accu0], % prepend the accumulator with the current element
treeToList(Left, Accu1, Accu2), % prepend elements of the left node
treeToList(Right, Accu2, List). % prepend elements of the right node
在排序的列表中计数要比在未排序的列表中计数容易得多。Prolog有一个内置的谓词
?- sort([9, 7, 8, 3, 1, 2, 6], L).
L = [1, 2, 3, 6, 7, 8, 9].
您可以计算相邻值的数量,并在一个步骤中获得剩余的不同值:
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).
使用该辅助对象是/3:
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
( % a semicolon is an either-or operator
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
并将一切结合起来:
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
全部代码:
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
treeToList(Tree, List) :-
treeToList(Tree, [], List).
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
treeToList(Left, [E|Accu0], Accu1),
treeToList(Right, Accu1, List).
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
(
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).
我对prolog非常陌生,所以这就是我得到的numberOfExcients(Ubt(),0)。NumberOfEmptures(E,bt(Root,LC,RC),N):-NumberOfEmptures(E,LC,Z),N是Z+1。我重写了我的答案。请看一看。很好的新方法!我正在用同样的旧竖琴演奏诗意起初我只想发表评论,但它却跑开了。:)@假与。从需求开始,重新编写它,直到它成为一个正确的定义。(他在年称之为“语义派生”)。以前从未知道这项工作(如果你不是在开“新”的玩笑,我最近在tag:prolog中发布了很多关于这种“泛化”代码派生技术的答案)。它总是以“从你已经拥有/知道的开始”或诸如此类的话开头你的第一步确实微不足道(属于逻辑部分),但对于初学者来说仍然很有洞察力。首先,获取(相对复杂的)查询并将其作为程序粘贴回去。我喜欢以类似的方式介绍简单递归谓词的开发,但从基本情况开始。当您介绍递归目标(没有语义上的正当性)时,会有一些挥手示意——可以详细说明。但是,这样的陈述总是吸引读者的直觉。@false将基本情况放在第一位是如此的口齿不清。:)我喜欢首先关注转换/关系的性质,关注我们正在做什么,而不是什么时候必须停止做(“停止做什么?”),因此,首先要处理非基本步骤。corecursion比递归更吸引我,它更关注本质;递归更具操作性,与终止有关,而corecursion则不关心,只关心步骤的生产率。基本情况类似于操作细节。Prolog的TRMC()在我第一次“了解”它时给我留下了深刻的印象。遵循“关注点分离”的设计理念,
countnextendent
可以进一步分为rle/2
?- countAdjacent([1,1,1,2,2,3], E, N).
E = 1, N = 3 ;
E = 2, N = 2 ;
E = 3, N = 1 ;
false.
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
?- numberOfOccurrences(E, bt(6, bt(2, bt(1, nil, nil),
bt(3, nil, nil)),
bt(8, bt(7, nil, nil),
bt(9, nil, nil))), L).
E = 1, L = 1 ;
E = 2, L = 1 ;
E = 3, L = 1 ;
E = 6, L = 1 ;
E = 7, L = 1 ;
E = 8, L = 1 ;
E = 9, L = 1 ;
false.
numberOfOccurrences(E, Tree, N) :-
treeToList(Tree, List),
sort(List, SortedList),
countAdjacent(SortedList, E, N).
treeToList(Tree, List) :-
treeToList(Tree, [], List).
treeToList(nil, Accu, Accu).
treeToList(bt(E, Left, Right), Accu0, List) :-
treeToList(Left, [E|Accu0], Accu1),
treeToList(Right, Accu1, List).
countAdjacent(List0, E, N) :-
[E0|List1] = List0,
removeFromFrontAndCount(E0, List1, List2, 1, CountE),
(
E = E0, N = CountE;
countAdjacent(List2, E, N)
).
removeFromFrontAndCount(_, [], [], N, N).
removeFromFrontAndCount(E, [F|Out], [F|Out], N, N) :-
E \= F.
removeFromFrontAndCount(E, [E|In], Out, N0, N2) :-
N1 is N0 + 1,
removeFromFrontAndCount(E, In, Out, N1, N2).