Perl,65 59 55 54字节
包括+2 -ap
在STDIN上以树大小运行:
for i in `seq 24`; do echo -n "$i: "; vines.pl <<< $i; echo; done
vines.pl
:
#!/usr/bin/perl -ap
$_=map{${"-@F"%$_}|=$_=$$_|$"x$p++.1;/.\b/g}1-$_..-1
说明
如果您重写树
3
|
2 4
\ /
1
|
0
到其中每个节点包含其所有祖先及其本身的集合的一个节点:
{3}
|
{2,3} {4}
\ /
\ /
{1,2,3,4}
|
{0,1,2,3,4}
然后,我们可以将例如所有节点从4到3的路径描述为:
- 所有包含3个但不包含4个的节点(从3个向下)
- 所有包含4个但不包含3个的节点(从4个向下)
- 包含3和4(联接)的最高节点
边的数量比节点的数量少1,因此我们可以使用它忽略连接点,因此从4到3的路径上的边的数量为3,因为:
- 包含3个但不包含4个的节点数:2个节点
- 包含4个节点但不包含3:1个节点的节点数
请注意,这也适用于直接下降到目标的路径,例如,对于从3到2的路径,边数为1,因为:
- 包含2个节点但不包含3个节点的节点数:0
- 包含3个节点但不包含2:1个节点的节点数
然后,我们可以总结所有这些组合。
如果您只看一个节点,例如具有祖先set的节点2 {2,3}
。该节点在处理路径时将贡献一次,2 to 1
因为它包含2而不是1。3 to 2
由于它同时具有2和3,因此它对路径没有任何贡献,但是在处理路径时4 to 3
由于它具有3但是却将贡献一次,但是否4.通常,节点的祖先集中的一个数字将为不在该集合中的每个邻居贡献一个(较高者中的较低者)。除了最大元素(在这种情况下为4)之外,最大元素仅对低邻居3起作用,因为没有路径5 to 4
。Simular 0是单面的,但是由于0总是在树的根部并且包含所有数字(这是最终联接,因此我们不计算联接)因此0永远不会有任何贡献,所以最简单的方法就是离开节点0一起出去。
因此,我们还可以通过查看每个节点的祖先集,计算贡献并求和所有节点的总和来解决该问题。
为了轻松处理邻居,我将祖先集表示为一串空格和1,其中位置p处的每个1表示n-1-p是祖先。因此,例如,n=5
在位置0 处为1 的情况下,表示4是祖先。我将保留尾随空格。因此,我将构建的树的实际表示为:
" 1"
|
" 11" "1"
\ /
\ /
"1111"
请注意,"11111"
由于我将忽略节点0(它永远不会起作用),所以我省略了用0表示的节点0。
现在,没有下位邻居的祖先由1序列的结尾表示。现在没有更高邻居的祖先由1的序列的开头表示,但是我们应该在字符串的开头忽略序列的任何开头,因为这将表示5 to 4
不存在的路径。正则表达式完全匹配此组合/.\b/
。
通过按顺序处理所有节点来构建祖先字符串,n-1 .. 1
并在该节点本身的位置上设置1并对后代执行“或”操作。
有了这个程序,所有这些都很容易理解:
-ap read STDIN into $_ and @F
map{ }1-$_..-1 Process from n-1 to 1,
but use the negative
values so we can use a
perl sequence.
I will keep the current
ancestor for node $i in
global ${-$i} (another
reason to use negative
values since $1, $2 etc.
are read-only
$$_|$"x$p++.1 "Or" the current node
position into its ancestor
accumulator
$_= Assign the ancestor string
to $_. This will overwrite
the current counter value
but that has no influence
on the following counter
values
${"-@F"%$_}|= Merge the current node
ancestor string into the
successor
Notice that because this
is an |= the index
calculation was done
before the assignment
to $_ so $_ is still -i.
-n % -i = - (n % i), so
this is indeed the proper
index
/.\b/g As explained above this
gives the list of missing
higher and lower neighbours
but skips the start
$_= A map in scalar context
counts the number of
elements, so this assigns
the grand total to $_.
The -p implicitly prints
请注意,替换/.\b/
为/\b/
解决了此问题的往返版本,其中tarzan也采用了该路径0 to n-1
有关祖先字符串外观的一些示例(按顺序提供n-1 .. 1
):
n=23:
1
1
1
1
1
1
1
1
1
1
1
11
1 1
1 1
1 1
11 11
1 1
11 1 1 11
1 1
1111 11 11 1111
111111111 111111111
1111111111111111111111
edges=68
n=24:
1
1
1
1
1
1
1
1
1
1
1
1
1 1
1 1
1 1
1 1
1 1
1 1 1 1
1 1
11 1 1 11
1 1 1 1
1 1 1 1
1 1
edges=82