Paraffins: Difference between revisions

43,601 bytes added ,  5 months ago
m
m (→‎{{header|REXX}}: fixed an HTML tag ending.)
m (→‎{{header|Wren}}: Minor tidy)
 
(33 intermediate revisions by 14 users not shown)
Line 1:
{{task}}
[[File:Paraffins.isopentane.png|450px600px||right]]
 
This organic chemistry task is essentially to implement a tree enumeration algorithm.
Line 6:
 
;Task:
Enumerate, without repetitions and in order of increasing size, all possible paraffin molecules (also known as [[wp:alkane|alkane]]s).
 
 
Paraffins are built up using only carbon atoms, which has four bonds, and hydrogen, which has one bond.   All bonds for each atom must be used, so it is easiest to think of an alkane as linked carbon atoms forming the "backbone" structure, with adding hydrogen atoms linking the remaining unused bonds.
 
In a paraffin, one is allowed neither double bonds (two bonds between the same pair of atoms), nor cycles of linked carbons. &nbsp; So all paraffins with &nbsp; '''n''' &nbsp; carbon atoms share the empirical formula &nbsp; &nbsp; <big>C<sub>n</sub>H<sub>2n+2</sub></big>
 
But for all &nbsp; '''n''' ≥ 4 &nbsp; there are several distinct molecules ("isomers") with the same formula but different structures.
Line 17:
The number of isomers rises rather rapidly when &nbsp; '''n''' &nbsp; increases.
 
In counting isomers it should be borne in mind that the four bond positions on a given carbon atom can be freely interchanged and bonds rotated (including 3-D "out of the paper" rotations when it's being observed on a flat diagram), &nbsp; so rotations or re-orientations of parts of the molecule (without breaking bonds) do not give different isomers. &nbsp; So what seem at first to be different molecules may in fact turn out to be different orientations of the same molecule.
 
 
;Example:
With &nbsp; '''n''' = 3 &nbsp; there is only one way of linking the carbons despite the different orientations the molecule can be drawn; &nbsp; and with &nbsp; '''n''' = 4 &nbsp; there are two configurations:
:::* &nbsp; a &nbsp; straight &nbsp; chain: &nbsp; &nbsp; <big>(CH<sub>3</sub>)(CH<sub>2</sub>)(CH<sub>2</sub>)(CH<sub>3</sub>)</big>
:::* &nbsp; a branched chain: &nbsp; &nbsp; &nbsp; <big>(CH<sub>3</sub>)(CH(CH<sub>3</sub>))(CH<sub>3</sub>)</big>
 
<br>
Line 34:
The output is how many different different paraffins there are with &nbsp; '''n''' &nbsp; carbon atoms (for instance &nbsp; 24,894 &nbsp; if &nbsp; '''n''' = 17).
 
The sequence of those results is visible in the [[oeisOEIS entry:A000602|Sloane encyclopedia]].&nbsp; The sequence is (the index starts from zero, and represents the number of carbon atoms):
::: &nbsp; [[oeis:A00602|A00602: number of n-node unrooted quartic trees; number of n-carbon alkanes C(n)H(2n+2) ignoring stereoisomers]].
 
The sequence is (the index starts from zero, and represents the number of carbon atoms):
 
1, 1, 1, 1, 2, 3, 5, 9, 18, 35, 75, 159, 355, 802, 1858, 4347, 10359,
Line 47 ⟶ 50:
A flat 1D representation, with arrays or lists is enough, for instance:
 
<langsyntaxhighlight haskelllang="text">*Main> all_paraffins 1
[CCP H H H H]
*Main> all_paraffins 2
[BCP (C H H H) (C H H H)]
*Main> all_paraffins 3
[CCP H H (C H H H) (C H H H)]
*Main> all_paraffins 4
[BCP (C H H (C H H H)) [BCP (C H H (C H H H)),CCP H (C H H H) (C H H H)),
CCP H (C H H H) (C H H H) (C H H H)]
(C H H H)]
*Main> all_paraffins 5
[CCP H H (C H H (C H H H)) (C H H (C H H H)),CCP H (C H H H)
(C H H H) (C H CCP H (C H H H)),CCP (C H H H) (C H H H) (C H H H)),
CCP (C H H H) (C H H H) (C H H H) (C H H H)]
(C H H H)]
*Main> all_paraffins 6
[BCP (C H H (C H H (C H H H))) (C H H (C H H (C H H H))),BCP
BCP (C H H (C H H (C H H H))) (C H (C H H H) (C H H H)),BCP (C H
BCP (C H (C H H H) (C H H H)) (C H (C H H H) (C H H H)),CCP H (C H H H)
(C H CCP H (C H H H)) (C H H (C H H H)),CCP (C H H H) (C H H H)),
CCP (C H H H) (C H H H) (C H H H) (C H H (C H H H))]</langsyntaxhighlight>
 
Showing a basic 2D ASCII-art representation of the paraffins is better; for instance (molecule names aren't necessary):
<presyntaxhighlight lang="text"> Methane methane ethane Ethane propane Propane Isobutaneisobutane
H H H H H H H H H
| | | | | | | | | │ │ │
H - C - H H - C - C - H H - C - C - C - H H - C - C - C - H
| | | | | | | | | │ │ │
H H H H H H H | H
|
H - C - H
|
H</presyntaxhighlight>
 
 
;Links:
* &nbsp; A paper that explains the problem and its solution in a functional language:
http://www.cs.wright.edu/~tkprasad/courses/cs776/paraffins-turner.pdf
 
* &nbsp; A Haskell implementation:
https://github.com/ghc/nofib/blob/master/imaginary/paraffins/Main.hs
 
* &nbsp; A Scheme implementation:
http://www.ccs.neu.edu/home/will/Twobit/src/paraffins.scm
 
* &nbsp; A Fortress implementation: &nbsp; &nbsp; &nbsp; &nbsp; (this site has been closed)
http://java.net/projects/projectfortress/sources/sources/content/ProjectFortress/demos/turnersParaffins0.fss?rev=3005
<br><br>
 
=={{header|11l}}==
{{trans|Nim}}
 
<syntaxhighlight lang="11l">V nMax = 250
V nBranches = 4
V rooted = [BigInt(0)] * (nMax + 1)
V unrooted = [BigInt(0)] * (nMax + 1)
rooted[0] = BigInt(1)
rooted[1] = BigInt(1)
unrooted[0] = BigInt(1)
unrooted[1] = BigInt(1)
 
F choose(m, k)
I k == 1
R m
V result = m
L(i) 1 .< k
result = result * (m + i) I/ (i + 1)
R result
 
F tree(br, n, l, sum, cnt)
V s = 0
L(b) br + 1 .. :nBranches
s = sum + (b - br) * n
I s > :nMax {R}
 
V c = choose(:rooted[n], b - br) * cnt
 
I l * 2 < s {:unrooted[s] += c}
I b == :nBranches {R}
:rooted[s] += c
L(m) (n - 1 .< 0).step(-1)
tree(b, m, l, s, c)
 
F bicenter(s)
I (s [&] 1) == 0
:unrooted[s] += :rooted[s I/ 2] * (:rooted[s I/ 2] + 1) I/ 2
 
L(n) 1 .. nMax
tree(0, n, n, 1, BigInt(1))
bicenter(n)
print(n‘: ’unrooted[n])</syntaxhighlight>
 
{{out}}
<pre>
1: 1
2: 1
3: 1
4: 2
5: 3
6: 5
7: 9
8: 18
9: 35
10: 75
...
244: 34576004768296889785887066794910718730985852896707505707076422305798138880427343561380451664648670542260
245: 96356944442415066997623733664230869603611716312377642117711752082444867783045964116385053282421589905891
246: 268540209617944059776303921971316267806082307732727328919911735252505071315985779867844056236080213000010
247: 748434113260252449609376828666343341456610378512725586135955779939163320693444008584504390382026391947130
248: 2086006351917005252913566124773054331962205157167696706926185063169623907656246841866717933958839366769700
249: 5814271898167303040368103945830220447130073898083466852225709084407144308593691069932064987528870826155297
250: 16206624309085062837751018464745815688226709117091506494175397665527493805947344857313038875654104100026504
</pre>
 
=={{header|C}}==
Can't show the tree shapes; count only.
<langsyntaxhighlight lang="c">#include <stdio.h>
 
#define MAX_N 33 /* max number of tree nodes */
Line 210 ⟶ 277:
 
return 0;
}</langsyntaxhighlight>Same idea, with GMP, and done somewhat differently:<langsyntaxhighlight lang="c">#include <gmp.h>
#include <stdio.h>
#include <stdlib.h>
Line 315 ⟶ 382:
 
return 0;
}</langsyntaxhighlight>
 
=={{header|C++}}==
<syntaxhighlight lang="c++">
#include <cstdint>
#include <iostream>
#include <vector>
 
const int32_t MAX_TREE_NODES = 52;
const int32_t MAX_BRANCHES = 4;
 
std::vector<uint64_t> rooted(MAX_TREE_NODES + 1, 0);
std::vector<uint64_t> unrooted(MAX_TREE_NODES + 1,0);
std::vector<uint64_t> count(MAX_BRANCHES, 0);
 
void tree(const int32_t& branches, const int32_t& radius, const int32_t& combinations,
const int32_t& previous_nodes, const uint64_t& branches_count) {
int32_t nodes = previous_nodes;
for ( int32_t branch = branches + 1; branch <= MAX_BRANCHES; ++branch ) {
nodes += radius;
 
if ( nodes > MAX_TREE_NODES || ( combinations * 2 >= nodes && branch >= MAX_BRANCHES ) ) {
return;
}
 
if ( branch == branches + 1 ) {
count[branches] = rooted[radius] * branches_count;
} else {
count[branches] *= ( rooted[radius] + branch - branches - 1 );
count[branches] /= ( branch - branches );
}
 
if ( combinations * 2 < nodes ) {
unrooted[nodes] += count[branches];
}
 
if ( branch < MAX_BRANCHES ) {
rooted[nodes] += count[branches];
}
 
for ( int32_t next_radius = radius - 1; next_radius > 0; --next_radius ) {
tree(branch, next_radius, combinations, nodes, count[branches]);
}
}
}
 
void bicenter(const int32_t& node) {
if ( ( node & 1 ) == 0 ) {
const uint64_t temp = ( rooted[node / 2] + 1 ) * rooted[node / 2];
unrooted[node] += temp / 2;
}
}
 
int main() {
rooted[0] = rooted[1] = 1;
unrooted[0] = unrooted[1] = 1;
 
for ( int32_t node = 1; node <= MAX_TREE_NODES; ++node ) {
tree(0, node, node, 1, 1);
bicenter(node);
std::cout << node << ": " << unrooted[node] << std::endl;
}
}
</syntaxhighlight>
{{ out }}
<pre>
1: 1
2: 1
3: 1
4: 2
5: 3
 
// elided
 
48: 156192366474590639
49: 417612400765382272
50: 1117743651746953270
51: 2994664179967370611
52: 8031081780535296591
</pre>
=={{header|D}}==
{{trans|Go}}
<langsyntaxhighlight lang="d">import std.stdio, std.bigint;
 
enum uint nMax = 250;
Line 362 ⟶ 508:
writeln(n, ": ", unrooted[n]);
}
}</langsyntaxhighlight>
{{out}}
<pre>1: 1
Line 391 ⟶ 537:
250: 16206624309085062837751018464745815688226709117091506494175397665527493805947344857313038875654104100026504</pre>
Run-time with nMax = 250 is about 3.6 seconds (about twice the Go entry using go1.2).
 
=={{header|FreeBASIC}}==
{{trans|Pascal}}
{{libheader|GMP}}
<langsyntaxhighlight lang="freebasic">' version 31-12-2016
' compile with: fbc -s console
' uses gmp, translation from pascal
Line 493 ⟶ 640:
Print : Print "hit any key to end program"
Sleep
End</langsyntaxhighlight>
<pre style="height:35ex;overflow:scroll"> 1: 1
2: 1
Line 997 ⟶ 1,144:
=={{header|Go}}==
{{trans|C}}
<langsyntaxhighlight lang="go">package main
 
import (
Line 1,057 ⟶ 1,204:
fmt.Printf("%d: %d\n", n, &unrooted[n])
}
}</langsyntaxhighlight>
Output: (trimmed)
<pre>
Line 1,108 ⟶ 1,255:
=={{header|Haskell}}==
Using formula from OEIS page, similar to the Mathematica entry below:
<langsyntaxhighlight lang="haskell">-- polynomial utils
a `nmul` n = map (*n) a
a `ndiv` n = map (`div` n) a
Line 1,151 ⟶ 1,298:
a602 = a678 - a599 + x2
 
main = mapM_ print $ take 200 $ zip [0 ..] a602</langsyntaxhighlight>
 
Counting trees with some fairly primitive caching:
<langsyntaxhighlight lang="haskell">import Data.Array
 
choose :: Integer -> Int -> Integer
Line 1,185 ⟶ 1,332:
| otherwise = x * (x + 1) `div` 2 where x = build_block (n `div` 2)
 
main = mapM_ print $ map (\x->(x, unrooted x)) [1..max_nodes]</langsyntaxhighlight>
{{out}}
<pre>
Line 1,210 ⟶ 1,357:
The following code is an interpretation of the Haskell program listed in the links above.
 
<langsyntaxhighlight lang="j">part3=: ;@((<@([(],.(-+/"1))],.]+i.@(]-~1+<.@-:@-))"0 i.@>:@<.@%&3))
 
part4=: 3 :0
Line 1,241 ⟶ 1,388:
)
 
NofParaff=: {. radGenN ((ccpGenN +:) + bcpGenN ) 2&|+<.@-:</langsyntaxhighlight>
Output:
<langsyntaxhighlight lang="j"> 6 6 $ NofParaff 36
1 1 1 1 2 3
5 9 18 35 75 159
Line 1,249 ⟶ 1,396:
60523 148284 366319 910726 2278658 5731580
14490245 36797588 93839412 240215803 617105614 1590507121
4111846763 10660307791 27711253769 72214088660 188626236139 493782952902</langsyntaxhighlight>
 
=={{header|Java}}==
Translation of [[Paraffins#C|C]] via [[Paraffins#Go|Go]] and [[Paraffins#D|D]]
<langsyntaxhighlight lang="java">import java.math.BigInteger;
import java.util.Arrays;
 
Line 1,311 ⟶ 1,458:
}
}
}</langsyntaxhighlight>
<pre>1: 1
2: 1
Line 1,333 ⟶ 1,480:
Currently jq uses IEEE 754 64-bit numbers. Large integers are approximated by floats and therefore the results generated by the program presented here are only precise for n up to and including 45.
 
<langsyntaxhighlight lang="jq">def MAX_N: 500; # imprecision begins at 46
def BRANCH: 4;
 
Line 1,397 ⟶ 1,544:
;
 
paraffins</langsyntaxhighlight>
'''Output''' (trimmed):
<pre style="height:35ex;overflow:scroll">$ jq -M -n -c -f paraffins.jq
Line 1,455 ⟶ 1,602:
{{works with|jq|>1.4}}
The following is a more elegant alternative to paraffins/0 as defined above but requires "foreach":
<langsyntaxhighlight lang="jq">def paraffins:
foreach range(1; MAX_N) as $n
( [unrooted, ra];
Line 1,461 ⟶ 1,608:
[$n, .[0][$n]]
)
;</langsyntaxhighlight>
 
=={{header|Julia}}==
{{trans|Go}}
Output is the same as the Go version.
<syntaxhighlight lang="julia">const branches = 4
const nmax = 500
 
const rooted = zeros(BigInt, nmax + 1)
const unrooted = zeros(BigInt, nmax + 1)
rooted[1] = rooted[2] = unrooted[1] = unrooted[2] = 1
const c = zeros(BigInt, branches)
 
function tree(br, n, l, sum, cnt)
for b in br+1:branches
sum += n
if (sum > nmax) || (l * 2 >= sum && b >= branches)
return
elseif b == br + 1
c[br + 1] = rooted[n + 1] * cnt
else
c[br + 1] *= rooted[n + 1] + b - br - 1
c[br + 1] = div(c[br + 1], b - br)
end
if l*2 < sum
unrooted[sum + 1] += c[br + 1]
end
if b < branches
rooted[sum + 1] += c[br + 1]
end
for m in n-1:-1:1
tree(b, m, l, sum, c[br + 1])
end
end
end
 
bicenter(n) = if iseven(n) unrooted[n + 1] += div(rooted[div(n, 2) + 1] * (rooted[div(n, 2) + 1] + 1), 2) end
 
function paraffins()
for n in 1:nmax
tree(0, n, n, 1, one(BigInt))
bicenter(n)
println("$n: $(unrooted[n + 1])")
end
end
 
paraffins()
</syntaxhighlight>
 
=={{header|Kotlin}}==
{{trans|Java}}
<langsyntaxhighlight lang="scala">// version 1.1.4-3
 
import java.math.BigInteger
Line 1,512 ⟶ 1,706:
println("$n: ${unrooted[n]}")
}
}</langsyntaxhighlight>
 
{{out}}
Line 1,519 ⟶ 1,713:
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
{{works with|Mathematica|9.0}}
Using the formula on OEIS.
<langsyntaxhighlight lang="mathematica">G000602s[m_, p_, n_] :=
CycleIndexPolynomial[SymmetricGroup[m],
Block[{x},
Table[ComposeSeries[p, x^i + O[x]^(n + 1)], {i, m}]];
x*CycleIndexPolynomial[SymmetricGroup[4],
G000598[n_] := Nest[1 + x s[3, #, n] Table[ComposeSeries[#&, x^i1 + O[x]^(n + 1)], {i, 4}n]] - ;
G000602[n_] :=
CycleIndexPolynomial[SymmetricGroup[2],
x s[4, #, n] - Table[ComposeSeriess[2, # - 1, x^i + O[x]^(n + 1)], {i, 2}]] +
ComposeSeries[#, x^2 + O[x]^(n + 1)] &@[G000598[n]];
Fold[Series[
1 + x/6 (#1^3 + 3 #1 ComposeSeries[#1, x^2 + O[x]^#2] +
2 ComposeSeries[#1, x^3 + O[x]^#2]), {x, 0, #2}] &,
1 + O[x], Range[n + 1]]];
A000602[n_] := SeriesCoefficient[G000602[n], n];
A000602List[n_] := CoefficientList[G000602[n], x];
Grid@Transpose@{Range[0, 200], A000602List@200}</langsyntaxhighlight>
{{Out}}
<pre>0 1
Line 1,557 ⟶ 1,747:
=={{header|Nim}}==
{{trans|C}}
<lang nim>import {{libheader|bigints}}
<syntaxhighlight lang="nim">import bigints
 
const
Line 1,570 ⟶ 1,761:
unrooted[i] = 0.initBigInt
 
proc choose(m,: BigInt; k: int32): BigInt =
result = m
if k == 1: return
for i in 1 .. < k:
result = result * (m + i) div (i + 1)
 
proc tree(br, n, l, sum: int32,; cnt: BigInt) =
var s: int32 = 0
for b in br + 1 .. nBranches:
Line 1,590 ⟶ 1,781:
tree b, m, l, s, c
 
proc bicenter(s: int32) =
if (s and 1) == 0:
unrooted[s] += rooted[s div 2] * (rooted[s div 2] + 1) div 2
Line 1,597 ⟶ 1,788:
tree 0, n, n, 1, 1.initBigInt
n.bicenter
echo n, ": ", unrooted[n]</langsyntaxhighlight>
 
Output:
{{out}}
<pre>1: 1
2: 1
Line 1,627 ⟶ 1,819:
 
This function is for recent PARI/GP:
<langsyntaxhighlight lang="parigp">paraffin(p) =
{
local (P = p+1, R, U = R = Vec([1,1], P));
Line 1,641 ⟶ 1,833:
if (n % 2,, U[n+1] += R[n/2+1] * (R[n/2+1]+1)/2);
print([n, U[n+1]]))
}</langsyntaxhighlight>
 
 
Code for older version of PARI/GP < 2.9:
<langsyntaxhighlight lang="parigp">iso(B,n,C,S,l=n) =
{
my (b,c,i,s);
Line 1,663 ⟶ 1,855:
if (n % 2,, U[n+1] += R[n/2+1] * (R[n/2+1]+1)/2);
print([n, U[n+1]]))
}</langsyntaxhighlight>
 
Output:<pre>paraffin(32)
Line 1,705 ⟶ 1,897:
{{libheader|GMP}}
Conversion of the C example:
<langsyntaxhighlight lang="pascal">Program Paraffins;
 
uses
Line 1,792 ⟶ 1,984:
mp_printf('%d: %Zd'+chr(13)+chr(10), n, @unrooted[n]);
end;
end.</langsyntaxhighlight>
Output (trimmed):
<pre>1: 1
Line 1,836 ⟶ 2,028:
</pre>
 
====Alternative method====
{{works with|Free_Pascal}}
This method of counting alkanes is based on a paper by Shinsaku Fujita (see program for reference). Multi-precision is not used, so alkanes are counted only up to order 49. The results are identical to those from the REXX program.
<syntaxhighlight lang="pascal">
program CountAlkanes;
 
{$mode objfpc}{$H+}
 
uses SysUtils; // only for output
 
type TArrayUint64 = array of uint64;
{
Function to count alkanes, based on: Shinsaku Fujita,
"Numbers of Alkanes and Monosubstituted Alkanes.
A Long-Standing Interdisciplinary Problem over 130 Years",
Bull. Chem. Soc. Jpn. Vol. 83, No. 1, 1–18 (2010)
}
function CountAlkanes() : TArrayUint64;
const
MAX_RESULT_INDEX = 49; // as far as this code can get without multi-precision
MAX_R_INDEX = MAX_RESULT_INDEX div 2;
var
R : array [0..MAX_R_INDEX] of uint64;
nrCentUnb : uint64; // number of centroidal unbalanced alkanes
temp : uint64;
m, n, h, i, j, k : integer;
begin
SetLength( result, MAX_RESULT_INDEX + 1); // zero-based
{
Calculate enough of the coefficients R[], where the generating function
r(x) = R[0] + R[1]x + R[2]x^2 + R[3]x^3 + ... satifies
r(x) = 1 + (x/6)[r(x)^3 + 2r(x^3) + 3r(x)r(x^2)] (Fujita, equation 4)
}
R[0] := 1;
n := 0;
repeat
if (n mod 3 = 0) then temp := 2*R[n div 3]
else temp := 0;
for j := 0 to (n div 2) do begin
inc( temp, 3 * R[j] * R[n - 2*j]);
end;
for j := 0 to n do begin
for k := 0 to (n - j) do begin
inc(temp, R[j] * R[k] * R[n - j - k]);
end;
end;
Assert( temp mod 6 = 0); // keep an eye on it
inc(n);
R[n] := temp div 6;
until (n = MAX_R_INDEX);
{
Now use the generating function
(x/24)[r(x)^4 + 3r(x^2)^2 + *r(x)r(x^3) + 6r(x)^2r(x^2) + 6r(x^4)]
where inserting r(x) up to the term in x^m will give the number of alkanes
of orders 2m+1 and 2m+2, as the coefficients of x^(2m+1) and x^(2m+2).
 
Note: In Fujita's paper, equation 23, the factor is 1/24 not x/24,
but x/24 seems to be needed to give correct results.
}
result[0] := 1; // conventional
for n := 1 to MAX_RESULT_INDEX do begin
m := (n - 1) div 2; // so n = 2*m + 1 or 2*m + 2
temp := 0;
 
// These loops are written for clarity not efficiency
for k := 0 to m do begin
for j := 0 to m do begin
for i := 0 to m do begin
h := n - 1 - i - j - k;
if (h >= 0) and (h <= m) then inc( temp, R[h]*R[i]*R[j]*R[k]);
end;
end;
end;
 
if Odd(n) then begin
for k := 0 to m do begin
inc( temp, 3*R[k]*R[m - k]);
end;
end;
 
for k := 0 to (n - 1) div 3 do begin
j := n - 1 - 3*k;
if (j <= m) then inc( temp, 8*R[j]*R[k]);
end;
 
for k := 0 to m do begin
for j := 0 to m do begin
i := n - 1 - 2*k - j;
if (i >= 0) and (i <= m) then inc( temp, 6*R[i]*R[j]*R[k]);
end;
end;
 
if (n mod 4 = 1) then inc( temp, 6*R[(n - 1) div 4]);
 
Assert( temp mod 24 = 0); // keep an eye on it
nrCentUnb := temp div 24;
if Odd(n) then
result[n] := nrCentUnb
else begin
temp := R[n div 2];
result[n] := nrCentUnb + (temp*(temp + 1) div 2);
end;
end;
end;
 
// Call function and display the results
var
nrAlkanes : TArrayUint64;
k : integer;
begin
nrAlkanes := CountAlkanes();
for k := 0 to Length( nrAlkanes) - 1 do
WriteLn( SysUtils.Format( '%2d %d', [k, nrAlkanes[k]]));
end.
</syntaxhighlight>
{{out}}
<pre>
0 1
1 1
2 1
3 1
4 2
5 3
6 5
[...]
48 156192366474590639
49 417612400765382272
</pre>
=={{header|Perl}}==
{{trans|C}}
This is using Math::GMPz for best performance. Math::GMP works almost as well. Math::BigInt is in core and only 9 times slower for this task.
<langsyntaxhighlight lang="perl">use Math::GMPz;
 
my $nmax = 250;
Line 1,878 ⟶ 2,199:
bicenter($n);
print "$n: $unrooted[$n]\n";
}</langsyntaxhighlight>
 
Output identical to C GMP example (truncated to 250).
 
=={{header|Perl 6Phix}}==
{{trans|Ruby}}
{{Works with|rakudo|2016.04}}
{{trans|FreeBASIC}}
 
Using IEEE754 floats, hence imprecise above n=45 on 32 bit, n=52 on 64bit, tested to n=600, giving 3.99378e+262 using %g format, ie accurate to better than 1e-10%.
Counting only, same algorithm as the C solution with some refactorings.
<!--<syntaxhighlight lang="phix">(phixonline)-->
 
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
Note how lexical scoping &mdash; rather than global variables or repeated arguments &mdash; is used to pass down information to subroutines.
<span style="color: #008080;">constant</span> <span style="color: #000000;">MAX_N</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">32</span><span style="color: #0000FF;">,</span>
 
<span style="color: #000000;">BRANCH</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span>
<lang perl6>sub count-unrooted-trees(Int $max-branches, Int $max-weight) {
my @rooted = flat 1,1,0 xx $max-weight - 1;
<span style="color: #004080;">sequence</span> <span style="color: #000000;">rooted</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">MAX_N</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">),</span>
my @unrooted = flat 1,1,0 xx $max-weight - 1;
<span style="color: #000000;">unrooted</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">MAX_N</span><span style="color: #0000FF;">+</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)</span>
 
sub count-trees-with-centroid(Int $radius) {
<span style="color: #008080;">procedure</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">br</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">=</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tot</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">atom</span> <span style="color: #000000;">cnt</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
sub add-branches(
<span style="color: #004080;">atom</span> <span style="color: #000000;">c</span>
Int $branches, # number of branches to add
<span style="color: #008080;">for</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">=</span><span style="color: #000000;">br</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">BRANCH</span> <span style="color: #008080;">do</span>
Int $w, # weight of heaviest branch to add
<span style="color: #000000;">tot</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">n</span>
Int $weight is copy, # accumulated weight of tree
<span style="color: #008080;">if</span> <span style="color: #000000;">tot</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">MAX_N</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
Int $choices is copy, # number of choices so far
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">tot</span> <span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">BRANCH</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
) {
$choices *<span style="color: @rooted[$w]#008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
for 1 .. $branches -> $b {
<span style="color: #004080;">integer</span> <span style="color: #000000;">n1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span>
($weight += $w) <= $max-weight or last;
<span style="color: #000000;">t1</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tot</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span>
@unrooted[$weight] += $choices if $weight > 2*$radius;
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">==</span><span style="color: #000000;">br</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span> <span style="color: #008080;">then</span>
if $b < $branches {
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n1</span><span style="color: #0000FF;">]*</span><span style="color: #000000;">cnt</span>
@rooted[$weight] += $choices;
<span style="color: #008080;">else</span>
add-branches($branches - $b, $_, $weight, $choices) for 1 ..^ $w;
<span style="color: #000000;">c</span> <span style="color: #0000FF;">*=</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n1</span><span style="color: #0000FF;">]+(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">-</span><span style="color: #000000;">br</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">))/(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">-</span><span style="color: #000000;">br</span><span style="color: #0000FF;">)</span>
$choices = $choices * (@rooted[$w] + $b) div ($b + 1);
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
}
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;"><</span><span style="color: #000000;">tot</span> <span style="color: #008080;">then</span>
}
<span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span>
}
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
add-branches($max-branches, $radius, 1, 1);
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;"><</span><span style="color: #000000;">BRANCH</span> <span style="color: #008080;">then</span>
}
<span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">t1</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">c</span>
 
<span style="color: #008080;">for</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
sub count-trees-with-bicentroid(Int $weight) {
<span style="color: #000000;">tree</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">,</span><span style="color: #000000;">m</span><span style="color: #0000FF;">,</span><span style="color: #000000;">l</span><span style="color: #0000FF;">,</span><span style="color: #000000;">tot</span><span style="color: #0000FF;">,</span><span style="color: #000000;">c</span><span style="color: #0000FF;">)</span>
if $weight %% 2 {
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
my \halfs = @rooted[$weight div 2];
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
@unrooted[$weight] += (halfs * (halfs + 1)) div 2;
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
}
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
}
 
<span style="color: #008080;">procedure</span> <span style="color: #000000;">bicenter</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
gather {
<span style="color: #008080;">if</span> <span style="color: #7060A8;">even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
take 1;
<span style="color: #004080;">atom</span> <span style="color: #000000;">aux</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
for 1 .. $max-weight {
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">1</span>
count-trees-with-centroid($_);
<span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">aux</span><span style="color: #0000FF;">*(</span><span style="color: #000000;">aux</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)/</span><span style="color: #000000;">2</span>
count-trees-with-bicentroid($_);
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
take @unrooted[$_];
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
}
}
<span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
}
<span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">1</span><span style="color: #0000FF;">..</span><span style="color: #000000;">2</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
 
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">MAX_N</span> <span style="color: #008080;">do</span>
my constant N = 100;
<span style="color: #000000;">tree</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
my @paraffins = count-unrooted-trees(4, N);
<span style="color: #000000;">bicenter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
say .fmt('%3d'), ': ', @paraffins[$_] for flat 1 .. 30, N;</lang>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><</span><span style="color: #000000;">10</span> <span style="color: #008080;">or</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">MAX_N</span> <span style="color: #008080;">then</span>
 
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d: %d\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<!--</syntaxhighlight>-->
{{out}}
<pre> 1: 1
21: 1
32: 1
43: 21
54: 32
65: 53
76: 95
87: 189
98: 3518
109: 7535
32: 27711253769
11: 159
</pre>
12: 355
And the same thing using gmp, obviously without any such accuracy limits
13: 802
<!--<syntaxhighlight lang="phix">(phixonline)-->
14: 1858
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
15: 4347
<span style="color: #008080;">constant</span> <span style="color: #000000;">max_n</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">200</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">branch</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">4</span>
16: 10359
<span style="color: #004080;">atom</span> <span style="color: #000000;">t0</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">time</span><span style="color: #0000FF;">()</span>
17: 24894
18: 60523
<span style="color: #008080;">include</span> <span style="color: #004080;">mpfr</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
19: 148284
<span style="color: #004080;">sequence</span> <span style="color: #000000;">ivals</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">)&</span><span style="color: #7060A8;">repeat</span><span style="color: #0000FF;">(</span><span style="color: #000000;">0</span><span style="color: #0000FF;">,</span><span style="color: #000000;">max_n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span>
20: 366319
<span style="color: #000000;">rooted</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">max_n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ivals</span><span style="color: #0000FF;">),</span>
21: 910726
<span style="color: #000000;">unrooted</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">max_n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #000000;">ivals</span><span style="color: #0000FF;">),</span>
22: 2278658
<span style="color: #000000;">c</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_inits</span><span style="color: #0000FF;">(</span><span style="color: #000000;">branch</span><span style="color: #0000FF;">,</span><span style="color: #000000;">0</span><span style="color: #0000FF;">)</span>
23: 5731580
<span style="color: #004080;">mpz</span> <span style="color: #000000;">tmp</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">()</span>
24: 14490245
25: 36797588
<span style="color: #008080;">procedure</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">br</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">mpz</span> <span style="color: #000000;">cnt</span><span style="color: #0000FF;">)</span>
26: 93839412
<span style="color: #004080;">mpz</span> <span style="color: #000000;">cbr</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">c</span><span style="color: #0000FF;">[</span><span style="color: #000000;">br</span><span style="color: #0000FF;">]</span>
27: 240215803
<span style="color: #008080;">for</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">=</span><span style="color: #000000;">br</span> <span style="color: #008080;">to</span> <span style="color: #000000;">branch</span> <span style="color: #008080;">do</span>
28: 617105614
<span style="color: #000000;">s</span> <span style="color: #0000FF;">+=</span> <span style="color: #000000;">n</span>
29: 1590507121
<span style="color: #008080;">if</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">></span><span style="color: #000000;">max_n</span>
30: 4111846763
<span style="color: #008080;">or</span> <span style="color: #0000FF;">(</span><span style="color: #000000;">l</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">s</span> <span style="color: #008080;">and</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">>=</span><span style="color: #000000;">branch</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
100: 5921072038125809849884993369103538010139</pre>
<span style="color: #008080;">return</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">=</span><span style="color: #000000;">br</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cbr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">cnt</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">else</span>
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">-</span><span style="color: #000000;">br</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cbr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cbr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_divexact_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">cbr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cbr</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">b</span><span style="color: #0000FF;">-</span><span style="color: #000000;">br</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;"><</span><span style="color: #000000;">s</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">u</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">u</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cbr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">b</span><span style="color: #0000FF;"><</span><span style="color: #000000;">branch</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">r</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">r</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cbr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">=</span><span style="color: #000000;">n</span><span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">1</span> <span style="color: #008080;">by</span> <span style="color: #0000FF;">-</span><span style="color: #000000;">1</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">tree</span><span style="color: #0000FF;">(</span><span style="color: #000000;">b</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">m</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">l</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cbr</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">bicenter</span><span style="color: #0000FF;">(</span><span style="color: #004080;">integer</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #7060A8;">even</span><span style="color: #0000FF;">(</span><span style="color: #000000;">s</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">then</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">aux</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">/</span><span style="color: #000000;">2</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">],</span>
<span style="color: #000000;">u</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">s</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">]</span>
<span style="color: #7060A8;">mpz_add_ui</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">aux</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_mul</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">aux</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_tdiv_q_2exp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #7060A8;">mpz_add</span><span style="color: #0000FF;">(</span><span style="color: #000000;">u</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">u</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">tmp</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
<span style="color: #004080;">mpz</span> <span style="color: #000000;">cnt</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">mpz_init</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">integer</span> <span style="color: #000000;">s</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">1</span>
<span style="color: #008080;">for</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">=</span><span style="color: #000000;">1</span> <span style="color: #008080;">to</span> <span style="color: #000000;">max_n</span> <span style="color: #008080;">do</span>
<span style="color: #000000;">tree</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">s</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">cnt</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">bicenter</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">)</span>
<span style="color: #008080;">if</span> <span style="color: #000000;">n</span><span style="color: #0000FF;"><=</span><span style="color: #000000;">25</span> <span style="color: #008080;">or</span> <span style="color: #7060A8;">remainder</span><span style="color: #0000FF;">(</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span><span style="color: #000000;">100</span><span style="color: #0000FF;">)=</span><span style="color: #000000;">0</span> <span style="color: #008080;">then</span>
<span style="color: #7060A8;">printf</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"%d: %s\n"</span><span style="color: #0000FF;">,{</span><span style="color: #000000;">n</span><span style="color: #0000FF;">,</span> <span style="color: #7060A8;">mpz_get_short_str</span><span style="color: #0000FF;">(</span><span style="color: #000000;">unrooted</span><span style="color: #0000FF;">[</span><span style="color: #000000;">n</span><span style="color: #0000FF;">+</span><span style="color: #000000;">1</span><span style="color: #0000FF;">])})</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">for</span>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">elapsed</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">time</span><span style="color: #0000FF;">()-</span><span style="color: #000000;">t0</span><span style="color: #0000FF;">)</span>
<!--</syntaxhighlight>-->
Unusually this is significantly faster (6*) under pwa/p2js than desktop/Phix, the following output/time is from the former.<br>
The limit of 200 in the code above finishes on desktop/Phix in 6s, p2js 1s, 500 takes about 40s in the browser but a whopping three and a half minutes on desktop/Phix, compared to the Go entry above completing that task in 15.6s, all on the same box of course. I have earmarked this task for further investigation into performance improvements, should Phix 2.0 ever actually get started on, that is.
{{out}}
<pre>
1: 1
2: 1
3: 1
4: 2
5: 3
6: 5
7: 9
8: 18
9: 35
10: 75
11: 159
12: 355
13: 802
14: 1858
15: 4347
16: 10359
17: 24894
18: 60523
19: 148284
20: 366319
21: 910726
22: 2278658
23: 5731580
24: 14490245
25: 36797588
100: 5921072038125809849884993369103538010139
200: 94304332879903850516...51576307818857723954 (84 digits)
300: 30845274893235665913...77084032710062170279 (129 digits)
400: 13544322063698139999...74867143490557738328 (174 digits)
500: 69888806977968318652...40565376686372508743 (218 digits)
600: 39937810748209753430...83373172999304809224 (263 digits)
"1 minute and 23s"
</pre>
 
=={{header|Pike}}==
{{trans|Python}}
<langsyntaxhighlight Pikelang="pike">int MAX_N = 300;
int BRANCH = 4;
Line 2,032 ⟶ 2,440:
write("%d: %d\n", n, unrooted[n]);
}
}</langsyntaxhighlight>
 
=={{header|Python}}==
This version only counts different paraffins. The multi-precision integers of Python avoid overflows.
{{trans|C}}
<langsyntaxhighlight lang="python">try:
import psyco
psyco.full()
Line 2,089 ⟶ 2,497:
print "%d: %d" % (n, unrooted[n])
 
main()</langsyntaxhighlight>
Output (newlines added):
<pre>1: 1
Line 2,139 ⟶ 2,547:
=== Using generating function ===
This is almost the same as the one in [[Formal power series]]. Compare to the Mathematica and Haskell solutions.
<langsyntaxhighlight lang="python">from itertools import count, chain, tee, islice, cycle
from fractions import Fraction
from sys import setrecursionlimit
Line 2,251 ⟶ 2,659:
a602 = a678 - a599 + x2
 
for n,x in zip(count(0), islice(a602, 500)): print(n,x)</langsyntaxhighlight>
 
=== Using generating function without OO ===
 
This uses a different generating function, but also demonstrates a lower level approach and the use of <code>functools.lru_cache</code> to memoise a recursive function which would otherwise make an exponential number of recursive calls.
 
<syntaxhighlight lang="python">#!/usr/bin/python3
 
from functools import lru_cache
 
def Z_S(n, f, k):
"""
The cycle index of the symmetric group has recurrence
Z(S_n, f(x)) = 1/n \sum_{i=1}^n f(x^i) Z(S_{n-i}, f(x)).
This function finds the coefficient of x^k in Z(S_n, f(x))
"""
# Special case to avoid division by zero
if n == 0:
return 1 if k == 0 else 0
# Special case as a speed optimisation
if n == 1:
return f(k)
return sum(
sum(f(ij // i) * Z_S(n-i, f, k - ij) for ij in range(0, k+1, i))
for i in range(1, n+1)
) // n
 
@lru_cache(maxsize=None)
def A000598(k): return 1 if k == 0 else Z_S(3, A000598, k-1)
 
@lru_cache(maxsize=None)
def A000642(k): return Z_S(2, A000598, k)
 
def A000631(k): return Z_S(2, A000642, k)
 
def A000602(k): return A000642(k) + (A000642((k-1) // 2) if k % 2 == 1 else 0) - A000631(k-1)
 
for k in range(500): print(k, A000602(k))</syntaxhighlight>
 
=={{header|Racket}}==
Line 2,257 ⟶ 2,702:
 
Or, a direct translation of the C entry:
<langsyntaxhighlight lang="racket">
#lang racket
 
Line 2,294 ⟶ 2,739:
(bicenter n)
(printf "~a: ~a\n" n (vector-ref unrooted n)))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{Works with|rakudo|2016.04}}
 
Counting only, same algorithm as the C solution with some refactorings.
 
Note how lexical scoping &mdash; rather than global variables or repeated arguments &mdash; is used to pass down information to subroutines.
 
<syntaxhighlight lang="raku" line>sub count-unrooted-trees(Int $max-branches, Int $max-weight) {
my @rooted = flat 1,1,0 xx $max-weight - 1;
my @unrooted = flat 1,1,0 xx $max-weight - 1;
 
sub count-trees-with-centroid(Int $radius) {
sub add-branches(
Int $branches, # number of branches to add
Int $w, # weight of heaviest branch to add
Int $weight is copy, # accumulated weight of tree
Int $choices is copy, # number of choices so far
) {
$choices *= @rooted[$w];
for 1 .. $branches -> $b {
($weight += $w) <= $max-weight or last;
@unrooted[$weight] += $choices if $weight > 2*$radius;
if $b < $branches {
@rooted[$weight] += $choices;
add-branches($branches - $b, $_, $weight, $choices) for 1 ..^ $w;
$choices = $choices * (@rooted[$w] + $b) div ($b + 1);
}
}
}
add-branches($max-branches, $radius, 1, 1);
}
 
sub count-trees-with-bicentroid(Int $weight) {
if $weight %% 2 {
my \halfs = @rooted[$weight div 2];
@unrooted[$weight] += (halfs * (halfs + 1)) div 2;
}
}
 
gather {
take 1;
for 1 .. $max-weight {
count-trees-with-centroid($_);
count-trees-with-bicentroid($_);
take @unrooted[$_];
}
}
}
 
my constant N = 100;
my @paraffins = count-unrooted-trees(4, N);
say .fmt('%3d'), ': ', @paraffins[$_] for flat 1 .. 30, N;</syntaxhighlight>
 
{{out}}
<pre> 1: 1
2: 1
3: 1
4: 2
5: 3
6: 5
7: 9
8: 18
9: 35
10: 75
11: 159
12: 355
13: 802
14: 1858
15: 4347
16: 10359
17: 24894
18: 60523
19: 148284
20: 366319
21: 910726
22: 2278658
23: 5731580
24: 14490245
25: 36797588
26: 93839412
27: 240215803
28: 617105614
29: 1590507121
30: 4111846763
100: 5921072038125809849884993369103538010139</pre>
 
=={{header|REXX}}==
(Based, in large part, on the '''Pascal''' version.)
 
Programming note: &nbsp; the biggest concern was calculating the number of numericdecimal digits &nbsp; (so as to avoid integer overflow).
<langsyntaxhighlight lang="rexx">/*REXX programpgm enumerates (without repetition) the #number of paraffins with N carbon atoms. of carbon*/
parse arg nodes . /*obtain optional argument from the CL.*/
if nodes=='' | nodes=="," then nodes=100 100 /*Not specified? Then use the default.*/
rooted. = 0; rooted.0= 1; rooted.1=1 1 /*define the base rooted numbers.*/
unrooted. = 0; unrooted.0= 1; unrooted.1=1 1 /* " " " unrooted " */
numeric digits max(9, nodes % 2) /*this program may use gihugeic numbers*/
w= length(nodes) /*W: used for aligning formatted nodes.*/
say right(0, w) unrooted.0 /*show enumerations of 0 carbon atoms*/
/* [↓] process all nodes (up to NODES)*/
do C=1 for nodes; h= C %2 2 /*C: is the number of carbon atoms. */
call tree 0, C, C, 1, 1 /* [↓] if # of carbon atoms is even···*/
if \(C//2==0) then unrooted.C= unrooted.C + rooted.h * (rooted.h + 1) % 2
say right(C, w) unrooted.C /*display an aligned formatted number. */
end /*C*/
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
tree: procedure expose rooted. unrooted. nodes #. /*this function is recursive.*/
parse arg br,n,L,sum,cnt; nm= n - 1; LL=L+L; brpLL=br L +1 L
brp= br + 1
do b=brp to 4; sum=sum+n; if sum>nodes then leave
if b==4 then do b=brp to 4; sum= if LL>=sum + then leaven
if b==brp then #.br=rooted.n * cnt if sum>nodes then leave
if b==4 else #.br=#.br * (rooted.n +then bif -LL>=sum brp) % (b -then br)leave
if LL<sumb==brp then unrooted#.sumbr=unrooted rooted.sumn +* #.brcnt
if b else #.br==4 #.br * (rooted.n + b - brp) % (b then- leavebr)
rooted. if LL<sum then unrooted.sum= rootedunrooted.sum + #.br
do m=nm by -1 for nm; call treeif b, m,==4 L, sum, #.br; end then /*m*/leave
end /*b*/ rooted.sum= rooted.sum + /* ↑↑↑↑↑↑↑↑↑ recursive invocation of TREE#. */</lang>br
do m=nm by -1 for nm; call tree b, m, L, sum, #.br
end /*m*/
end /*b*/ /* ↑↑↑↑↑↑↑↑↑ recursive. */
return</syntaxhighlight>
{{out|output|text=&nbsp; when using the input of: &nbsp; &nbsp; <tt> 600 </tt>}}
 
<br><br>(Shown at four-fifths size.)
(Shown at three-quarter size.)
<pre style="font-size:84%;height:99ex">
<pre style="font-size:75%;height:150ex">
0 1
1 1
Line 2,935 ⟶ 3,472:
=={{header|Ruby}}==
{{trans|Python}}
<langsyntaxhighlight lang="ruby">MAX_N = 500
BRANCH = 4
 
Line 2,970 ⟶ 3,507:
bicenter(n)
puts "%d: %d" % [n, $unrooted[n]]
end</langsyntaxhighlight>
{{out}}
<pre>
Line 3,015 ⟶ 3,552:
 
=={{header|Scala}}==
<langsyntaxhighlight Scalalang="scala">object Paraffins extends App {
val (nMax, nBranches) = (250, 4)
val rooted, unrooted = Array.tabulate(nMax + 1)(i => if (i < 2) BigInt(1) else BigInt(0))
Line 3,048 ⟶ 3,585:
println(f"$n%3d: ${unrooted(n)}%s")
}
}</langsyntaxhighlight>
{{Out}}See it in running in your browser by [https://scalafiddle.io/sf/JjR1R6k/2 ScalaFiddle (JavaScript)] or by [https://scastie.scala-lang.org/QycB9fBTTYG890zKOqREVw Scastie (JVM)].
 
=={{header|Seed7}}==
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
include "bigint.s7i";
 
Line 3,113 ⟶ 3,650:
writeln(n <& ": " <& unrooted[n]);
end for;
end func;</langsyntaxhighlight>
 
Output (trimmed):
Line 3,150 ⟶ 3,687:
{{trans|C}}
Handles arbitrarily large values.
<langsyntaxhighlight lang="tcl">package require Tcl 8.5
 
set maxN 200
Line 3,195 ⟶ 3,732:
bicenter $n
puts "${n}: [lindex $unrooted $n]"
}</langsyntaxhighlight>
 
=={{header|Wren}}==
{{trans|Go}}
{{libheader|Wren-big}}
{{libheader|Wren-fmt}}
<syntaxhighlight lang="wren">import "./big" for BigInt
import "./fmt" for Fmt
 
var branches = 4
var nMax = 250
var rooted = List.filled(nMax + 1, BigInt.zero)
var unrooted = List.filled(nMax + 1, BigInt.zero)
var c = List.filled(branches, BigInt.zero)
 
var tree
tree = Fn.new { |br, n, l, sum, cnt|
var b = br + 1
while (b <= branches) {
sum = sum + n
if (sum > nMax) return
if (l*2 >= sum && b >= branches) return
if (b == br + 1) {
c[br] = rooted[n] * cnt
} else {
var tmp = rooted[n] + BigInt.new(b - br - 1)
c[br] = c[br] * tmp
c[br] = c[br] / BigInt.new(b - br)
}
if (l*2 < sum) unrooted[sum] = unrooted[sum] + c[br]
if (b < branches) rooted[sum] = rooted[sum] + c[br]
var m = n - 1
while (m > 0) {
tree.call(b, m, l, sum, c[br])
m = m - 1
}
b = b + 1
}
}
 
var bicenter = Fn.new { |s|
if (s%2 == 0) {
var tmp = (rooted[(s/2).floor] + BigInt.one) * rooted[(s/2).floor]
tmp = tmp >> 1
unrooted[s] = unrooted[s] + tmp
}
}
 
rooted[0] = BigInt.one
rooted[1] = BigInt.one
unrooted[0] = BigInt.one
unrooted[1] = BigInt.one
for (n in 1..nMax) {
tree.call(0, n, n, 1, BigInt.one)
bicenter.call(n)
Fmt.print("$3d: $i", n, unrooted[n])
}</syntaxhighlight>
 
{{out}}
Abbreviated.
<pre>
1: 1
2: 1
3: 1
4: 2
5: 3
6: 5
7: 9
8: 18
9: 35
10: 75
11: 159
12: 355
13: 802
14: 1858
15: 4347
16: 10359
17: 24894
18: 60523
19: 148284
20: 366319
21: 910726
22: 2278658
23: 5731580
24: 14490245
25: 36797588
26: 93839412
27: 240215803
28: 617105614
29: 1590507121
30: 4111846763
31: 10660307791
32: 27711253769
33: 72214088660
34: 188626236139
35: 493782952902
...
249: 5814271898167303040368103945830220447130073898083466852225709084407144308593691069932064987528870826155297
250: 16206624309085062837751018464745815688226709117091506494175397665527493805947344857313038875654104100026504
</pre>
 
=={{header|zkl}}==
Line 3,201 ⟶ 3,837:
{{trans|Go}}
Uses GMP for big ints, mostly modified in place. Rather slow.
<langsyntaxhighlight lang="zkl">var BN=Import("zklBigNum");
 
const nMax=100, nBranches=4;
Line 3,235 ⟶ 3,871:
bicenter(n);
println(n, ": ", unrooted[n]);
}</langsyntaxhighlight>
{{out}}
<pre>
9,490

edits