Perl, 65 59 55 54 bayt
İçin +2 içerir -ap
STDIN'de ağaç boyuyla koş:
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
açıklama
Ağacı yeniden yazarsan
3
|
2 4
\ /
1
|
0
her düğümün atalarının ve kendi kümelerinin bulunduğu bir yere:
{3}
|
{2,3} {4}
\ /
\ /
{1,2,3,4}
|
{0,1,2,3,4}
O zaman örneğin tüm düğümleri 4 - 3 arasındaki yolu şöyle tanımlayabiliriz:
- 3 içeren ancak 4 olmayan tüm düğümler (3'ten aşağıya iniyor)
- 4 içeren ancak 3 olmayan tüm düğümler (4'ten aşağıya iniyor)
- Hem 3 hem de 4'ü içeren en yüksek düğüm (birleştirme)
Kenarların sayısı düğüm sayısından daha azdır, bu nedenle birleşme noktasını yoksaymak için kullanabiliriz, bu nedenle yoldaki kenar sayısı 4'ten 3'e kadardır, çünkü:
- 3 içeren ancak 4: 2 düğüm içermeyen düğümlerin sayısı
- 4 içeren ancak 3: 1 düğüm içermeyen düğümlerin sayısı
Bunun doğrudan hedefine inen bir yol için de işe yaradığına dikkat edin, örneğin 3 ila 2 arasındaki yol için kenar sayısı 1'dir:
- 2 içeren ancak 3: 0 düğüm içermeyen düğüm sayısı
- 3: 2: 1 düğümü içermeyen düğümlerin sayısı
Daha sonra tüm bu kombinasyonları toplayabiliriz.
Bunun yerine sadece bir düğüme bakarsanız, örneğin ata setli 2. düğüm {2,3}
. Bu düğüm yolu 2 to 1
2'ye 1 ama içerdiği için yol açtığında bir kez katkıda bulunacak. 3 to 2
Hem 2 hem de 3'e sahip olduğu için yol için hiçbir şeye katkıda bulunmayacak , ancak 3'ten 4 to 3
beri yolu işlerken bir kez katkıda bulunacak , ancak hayır 4. Genel olarak, bir düğüm kümesinin ata kümesindeki bir sayı, kümede olmayan her komşu için bir tane (daha aşağıdan yukarıya) katkıda bulunacaktır. Yolun olmadığından, sadece düşük komşu 3'e katkıda bulunan azami unsur (bu durumda 4) hariç5 to 4
. Simüler 0 tek taraflıdır, ancak 0 her zaman ağacın kökündeyken ve tüm sayıları içerdiğinden (nihai birleşme ve birleştirme sayılmaz) 0'dan hiçbir zaman katkısı olmaz. tamamen dışarı.
Böylece sorunu, her düğüm için belirlenen ataya bakarak çözebiliriz, katkıları sayabilir ve tüm düğümler üzerinde toplayabiliriz.
Komşuları kolayca işlemek için ata kümelerini bir boşluk dizesi olarak temsil edeceğim ve p pozisyonundaki her bir 1'in n-1-p'nin bir ata olduğunu temsil ettiği yerlerden biri. Dolayısıyla, örneğin bizim durumumuzda n=5
0, 0 konumunda, 4'ün bir ata olduğunu belirtir. Sondaki boşlukları bırakacağım. Yani inşa edeceğim ağacın gerçek temsili şudur:
" 1"
|
" 11" "1"
\ /
\ /
"1111"
Düğüm 0'ı "11111"
yoksaymayacağım için (hiçbir zaman katkıda bulunmaz) gösterdiğim için düğüm 0'ı dışarıda bıraktığımı fark et .
Alt komşusu olmayan atalar şimdi 1'lerin sırasının sonu ile temsil edilir. Daha yüksek komşusu olmayan atalar, şimdi 1'lerin bir dizisinin başlangıcıyla temsil edilir, ancak bir dizgenin başlangıcındaki herhangi bir dizinin başlangıcını yoksaymalıyız, çünkü bu 5 to 4
varolmayan yolu temsil edecektir . Bu kombinasyon tam olarak regex ile eşleştirilir /.\b/
.
Ata dizgilerinin oluşturulması, tüm düğümlerin sırayla işlenmesiyle yapılır n-1 .. 1
ve burada düğümün kendisinde bir 1 belirlenir ve soyundan bir "veya" yapılır.
Tüm bunlarla programın anlaşılması kolaydır:
-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
Bunun yerine /.\b/
, /\b/
tarzan'ın da yol açtığı bu sorunun gidiş dönüş sürümünü çözdüğüne dikkat edin0 to n-1
Ata dizelerinin nasıl göründüğüne dair bazı örnekler (sıra ile verilmiştir 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