转载自:https://mp.weixin.qq.com/s/BnSalO-hEPI-E7jmL2Pqnw
给定具有n节点的树(因此有n-1边)。找到一种方法,从枚举节点1到n,因此,从边1到边n-1以这样的方式,对于每个边k其节点号的差等于k。推测这总是可能的。
这是一个例子,可以很清楚地说明这一点:
我们的任务
我们的代码将以一棵树作为输入,我们可以采用所需的格式,但是对于测试用例,我们将通过它们的弧和它们的节点列表来提供树。
例如,这是图片中树的输入:
[d-a,a-g,b-c,e-f,b-e,a-b]
您的代码必须返回带有编号的节点树。您可以返回更多图形输出,但是我将为测试用例提供这种输出:
[a/1,b/5,c/2,d/3,e/4|_8892]
测试用例:
1、[a-b,b-c,c-d,c-e] => [a/1,b/5,c/2,d/3,e/4|_8892]
2、[d-a,a-g,b-c,e-f,b-e,a-b] => [a/1,b/5,d/6,g/7,c/2,e/3,f/4|_9492]
3、[g-a,i-a,a-h,b-a,k-d,c-d,m-q,p-n,q-n,e-q,e-c,f-c,c-a] => [a/1,b/2,c/12,g/11,h/13,i/14,d/3,e/4,f/5,k/8,q/10,m/6,n/7,p/9|_12486]
下面是具体的程序:
程序文件名:p7_03.pl
:- ensure_loaded('../Graphs/p6_01').
% 程序文件见:图 练习1
:- ensure_loaded('../Graphs/p6_04'). % is_tree
% 程序文件见:图 练习3
% vonkoch(G,Enum) :- 可以如Enum中所述枚举图G的节点。枚举是X/K对的列表,其中X是节点,K是对应的数字。
vonkoch(Graph,Enum) :-
is_tree(Graph), % 做太多工作之前先检查一下!
Graph = graph(Ns,_),
length(Ns,N),
human_gterm(Hs,Graph),
vonkoch(Hs,N,Enum).
vonkoch([IsolatedNode],1,[IsolatedNode/1|_]). % 特殊情况
vonkoch(EdgeList,N,Enum) :-
range(1,N,NodeNumberList),
N1 is N-1,range(1,N1,EdgeNumberList),
bind(EdgeList,NodeNumberList,EdgeNumberList,Enum).
% 该树作为边列表给出;例如 [d-a,a-g,b-c,e-f,b-e,a-b].
% 我们的问题是找到节点(a,b,c,...)与整数1..N之间的双射,这与上面提到的条件兼容。为了构造这个双射,我们使用一个开放式列表Enum;然后我们扫描给定的边列表。
bind([],_,_,_) :- !.
bind([V1-V2|Es],NodeNumbers,EdgeNumbers,Enum) :-
bind_node(V1,K1,NodeNumbers,NodeNumbers1,Enum),
bind_node(V2,K2,NodeNumbers1,NodeNumbers2,Enum),
D is abs(K1-K2), select(D,EdgeNumbers,EdgeNumbers1),
bind(Es,NodeNumbers2,EdgeNumbers1,Enum).
% bind_node(V,K,NodeNumsIn,NodeNumsOut,Enum) :-
% V/K是列表Enum的元素,并且没有V1 \= V使得V1/K在Enum中,也没有K1 \= K使得V =:= K1在Enum中。如果V获得一个新数字,则从设置的NodeNumsIn中选择它;剩下的就是NodeNumsOut。
% (node,integer,integer-list,integer-list,enumeration) (+,?,+,-,?)
bind_node(V,K,NodeNumbers,NodeNumbers,Enum) :-
memberchk(V/K1,Enum), number(K1), !, K = K1.
bind_node(V,K,NodeNumbers,NodeNumbers1,Enum) :-
select(K,NodeNumbers,NodeNumbers1), memberchk(V/K,Enum).
% range(A,B,L) :- L是数字A..B的列表
range(B,B,[B]) :- !.
range(A,B,[A|L]) :-
A < B,
A1 is A+1,
range(A1,B,L).
% test suite ------------------------------------------------------------
test_Von(K) :-
test_tree(K,TH),
write(TH), nl,
human_gterm(TH,T),
vonkoch(T,Enum),
write(Enum).
test_tree(1,[a-b,b-c,c-d,c-e]).
test_tree(2,[d-a,a-g,b-c,e-f,b-e,a-b]).
test_tree(3,[g-a,i-a,a-h,b-a,k-d,c-d,m-q,p-n,q-n,e-q,e-c,f-c,c-a]).
test_tree(4,[a]).
测试:
?- consult('p7_03.pl').
true.
?- test_Von(1).
[a-b,b-c,c-d,c-e]
[a/1,b/5,c/2,d/3,e/4|_8892]
true .
?- test_Von(2).
[d-a,a-g,b-c,e-f,b-e,a-b]
[a/1,b/5,d/6,g/7,c/2,e/3,f/4|_9492]
true .
?- test_Von(3).
[g-a,i-a,a-h,b-a,k-d,c-d,m-q,p-n,q-n,e-q,e-c,f-c,c-a]
[a/1,b/2,c/12,g/11,h/13,i/14,d/3,e/4,f/5,k/8,q/10,m/6,n/7,p/9|_12486]
true .
?- test_Von(4).
[a]
[a/1|_8098]
true .
?-