Triangular numbers

Revision as of 13:45, 10 February 2023 by Horst (talk | contribs) (→‎{{header|Raku}}: perpend Free Pascal)

A triangular number is a count of objects arranged into an equilateral triangle. Much like how a square number is a count of objects arranged into a square.

Triangular numbers is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

The nth triangular number is the sum of the first n non-negative integers.

Triangular numbers may be calculated by the following explicit formulas:

where is the binomial coefficient "n plus one choose two".


Analogous to square roots, we may also calculate a triangular root. Numbers that have an integer triangular root are triangular numbers.

The real triangular root of a number x may be found using:


Similar to how cubic numbers are square numbers extended into a third dimension, triangular numbers extended into a third dimension are known as tetrahedral numbers.

The nth tetrahedral number is the sum of the first n triangular numbers.

Or, may be calculated directly: (Binomial "n plus two choose three".)

One may find the real tetrahedral root of x using the formula:
Depending on the math precision of your particular language, may need to be rounded to the nearest 1e-16 or so.


Extending into a fourth dimension we get pentatopic numbers.

Again, the nth pentatope is the sum of the first n tetrahedral numbers, or (Binomial "n plus three choose four".)

The pentatopic real root of x may be found using:


In general, these all belong to the class figurate numbers as they are based on r dimensional geometric figures. Sometimes they are referred to as r-simplex numbers. In geometry a simplex is the simplest r-dimensional object possible.

You may easily extend to an arbitrary dimension r using binomials. Each term n in dimension r is

There is no known general formula to find roots of higher r-simplex numbers.


Task
  • Find and display the first 30 triangular numbers (r = 2).
  • Find and display the first 30 tetrahedral numbers (r = 3).
  • Find and display the first 30 pentatopic numbers (r = 4).
  • Find and display the first 30 12-simplex numbers (r = 12).
  • Find and display the triangular root, the tetrahedral root, and the pentatopic root for the integers:
    • 7140
    • 21408696
    • 26728085384
    • 14545501785001


See also


Julia

Translation of: Raku
""" rosettacode.org task Triangular_numbers """


polytopic(r, range) = map(n -> binomial(n + r - 1, r), range)

triangular_root(x) = (sqrt(8x + 1) - 1) / 2

function tetrahedral_root(x)
    return Float64(round((3x + sqrt(9 * big(x)^2 - 1/27))^(1/3) +
       (3x - sqrt(9 * big(x)^2 - 1/27))^(1/3) - 1, digits=11))
end

pentatopic_root(x) = (sqrt(5 + 4 * sqrt(24x + 1)) - 3) / 2

function valuelisting(a, N=6)
    c = maximum(length, string.(a)) + 1
    return join([join([lpad(x, c) for x in v]) for v in Iterators.partition(a, N)], "\n")
end

for (r, name) in [[2, "triangular"], [3, "tetrahedral"], [4, "pentatopic"], [12, "12-simplex"]]
    println("\nFirst 30 $name numbers:\n", valuelisting(polytopic(r, 0:29)))
end

for n in [7140, 21408696, 26728085384, 14545501785001]
    println("\nRoots of $n:")
    println("   triangular-root: ", triangular_root(n))
    println("   tetrahedral-root: ", tetrahedral_root(n))
    println("   pentatopic-root: ", pentatopic_root(n))
end
Output:
First 30 triangular numbers:
   0   1   3   6  10  15
  21  28  36  45  55  66
  78  91 105 120 136 153
 171 190 210 231 253 276
 300 325 351 378 406 435

First 30 tetrahedral numbers:
    0    1    4   10   20   35
   56   84  120  165  220  286
  364  455  560  680  816  969
 1140 1330 1540 1771 2024 2300
 2600 2925 3276 3654 4060 4495

First 30 pentatopic numbers:
     0     1     5    15    35    70
   126   210   330   495   715  1001
  1365  1820  2380  3060  3876  4845
  5985  7315  8855 10626 12650 14950
 17550 20475 23751 27405 31465 35960

First 30 12-simplex numbers:
          0          1         13         91        455       1820
       6188      18564      50388     125970     293930     646646
    1352078    2704156    5200300    9657700   17383860   30421755
   51895935   86493225  141120525  225792840  354817320  548354040
  834451800 1251677700 1852482996 2707475148 3910797436 5586853480

Roots of 7140:
   triangular-root: 119.0
   tetrahedral-root: 34.0
   pentatopic-root: 18.876646615928006

Roots of 21408696:
   triangular-root: 6543.0
   tetrahedral-root: 503.56182697464
   pentatopic-root: 149.06094737526587

Roots of 26728085384:
   triangular-root: 231205.40556525585
   tetrahedral-root: 5432.0
   pentatopic-root: 893.4424567516849

Roots of 14545501785001:
   triangular-root: 5.3936071581451725e6
   tetrahedral-root: 44355.77738407323
   pentatopic-root: 4321.0

Pascal

Pascal

Using only extended isn't that precise for tetrahedral roots.
sqrt(sqr(3x)+1/27) is nearly 3x for bigger x values.

program XangularNumbers;
const 
  MAXIDX = 29;
  MAXLINECNT = 13;
  cNames : array[0..4] of string =
     ('','','triangular','tetrahedral','pentatopic');
  cCheckRootValues :array[0..3] of Uint64 = 
       (7140,21408696,26728085384,14545501785001)   ;
type
  tOneLine  = array[0..MAXIDX+2] of Uint64;
  tpOneLine = ^tOneLine;
  tSimplexs  = array[0..MAXLINECNT-1] of tOneLine;  

procedure OutLine(var S:tSimplexs;idx: NativeInt);
const
  cColCnt = 6;cColWidth = 80 DIV cColCnt;
var
  i,colcnt : NativeInt;
begin
  if idx > High(cNames) then
    writeln('First ',MAXIDX+1,' ',idx,'-simplex numbers')  
  else
    writeln('First ',MAXIDX+1,' ',cNames[idx],' numbers');
  colcnt := cColCnt;
  For i := 0 to MAXIDX do
  begin
    write(S[idx,i]:cColWidth);
    dec(colCnt);
    if ColCnt = 0 then
    Begin
      writeln;
      ColCnt := cColCnt;
    end;
  end; 
  if ColCnt <  cColCnt then
    writeln;
  writeln;   
end;  

procedure CalcNextLine(var S:tSimplexs;idx: NativeInt);  
var
  s1,s2: Uint64;  
  i : NativeInt;
begin
  s1 := S[idx,0];  
  S[idx+1,0] := s1;
  For i := 1 to MAXIDX do
  begin
    s2:= S[idx,i];
    S[idx+1,i] := s1+s2;
    inc(s1,s2);
  end;  
end;

procedure InitSimplexs(var S:tSimplexs);
var
  i: NativeInt;
begin
  fillChar(S,Sizeof(S),#0);
  For i := 1 to MAXIDX do
    S[0,i] := 1;
  For i := 0 to MAXLINECNT-2 do    
    CalcNextLine(S,i);    
end;

function TriangularRoot(n: Uint64): extended;
begin
  if n < High(Uint64) DIV 8 then
    TriangularRoot := (sqrt(8*n+1)-1) / 2
  else
    TriangularRoot := (sqrt(8)*sqrt(n)-1)/2;
end;  

function tetrahedralRoot(n: Uint64): extended;
const
  cRec27 = 1/sqrt(27);
var
  x,y : extended;
begin
  y := 3.0*n;  
  x := sqrt((y-cRec27)*(y+cRec27));//sqrt(sqr(3*n)-1/27)
  if x < y then
    tetrahedralRoot := exp(ln(y+x)/3.0)+exp(ln(y-x)/3.0)-1.0
  else
    //( 6*n)^(1/3)-1
    tetrahedralRoot :=exp(ln(6)/3.0)*exp(ln(n)/3.0)-1.0; //6^(1/3)* n^(1/3)-1  
end;

function PentatopicRoot(n: Uint64): extended;
begin
  PentatopicRoot := (sqrt(5 + 4 * sqrt(24*n + 1)) - 3) / 2;
end; 

var
  Simplexs  : tSimplexs;
  n : Uint64;
  i : NativeInt;
Begin
  InitSimplexs(Simplexs);
  OutLine(Simplexs,2);
  OutLine(Simplexs,3);
  OutLine(Simplexs,4);
  OutLine(Simplexs,12);
  For i := 0 to High(cCheckRootValues) do
  begin
    n := cCheckRootValues[i];
    writeln('Roots of ',n,':');
    writeln('triangular -root : ',TriangularRoot(n):20:12);
    writeln('tetrahedral-root : ',tetrahedralRoot(n):20:12);
    writeln('pentatopic -root : ',PentatopicRoot(n):20:12);
    writeln;
  end;
end.
Output:
First 30 triangular numbers
            0            1            3            6           10           15
           21           28           36           45           55           66
           78           91          105          120          136          153
          171          190          210          231          253          276
          300          325          351          378          406          435

First 30 tetrahedral numbers
            0            1            4           10           20           35
           56           84          120          165          220          286
          364          455          560          680          816          969
         1140         1330         1540         1771         2024         2300
         2600         2925         3276         3654         4060         4495

First 30 pentatopic numbers
            0            1            5           15           35           70
          126          210          330          495          715         1001
         1365         1820         2380         3060         3876         4845
         5985         7315         8855        10626        12650        14950
        17550        20475        23751        27405        31465        35960

First 30 12-simplex numbers
            0            1           13           91          455         1820
         6188        18564        50388       125970       293930       646646
      1352078      2704156      5200300      9657700     17383860     30421755
     51895935     86493225    141120525    225792840    354817320    548354040
    834451800   1251677700   1852482996   2707475148   3910797436   5586853480

Roots of 7140:
triangular -root :     119.000000000000
tetrahedral-root :      34.000000000003
pentatopic -root :      18.876646615928

Roots of 21408696:
triangular -root :    6543.000000000000
tetrahedral-root :     503.561826261328
pentatopic -root :     149.060947375266

Roots of 26728085384:
triangular -root :  231205.405565255837
tetrahedral-root :    5431.999938646542 <<==
pentatopic -root :     893.442456751685

Roots of 14545501785001:
triangular -root : 5393607.158145172316
tetrahedral-root :   44355.777376558433
pentatopic -root :    4321.000000000000

Raku

use Math::Root;

my \ε = FatRat.new: 1, 10**24;

sub binomial { [×] ($^n0) Z/ 1 .. $^p }

sub polytopic (Int $r, @range) { @range.map: { binomial $_ + $r - 1, $r } }

sub triangular-root ($x) { round ((8 × $x + 1).&root - 1) / 2, ε }

sub tetrahedral-root ($x) {
    ((3 × $x + (9 × $x² - 1/27).&root).&root(3) +
     (3 × $x - (9 × $x² - 1/27).&root).&root(3) - 1).round: ε
}

sub pentatopic-root ($x) { round ((5 + 4 × (24 × $x + 1).&root).&root - 3) / 2, ε }

sub display (@values) {
    my $c = @values.max.chars;
    @values.batch(6)».fmt("%{$c}d").join: "\n";
}

for 2, 'triangular', 3, 'tetrahedral', 4, 'pentatopic', 12, '12-simplex'
  -> $r, $name { say "\nFirst 30 $name numbers:\n" ~ display polytopic $r, ^30 }

say '';

for 7140, 21408696, 26728085384, 14545501785001 {
  say qq:to/R/;
  Roots of $_:
    triangular-root: {.&triangular-root}
   tetrahedral-root: {.&tetrahedral-root}
    pentatopic-root: {.&pentatopic-root}
  R
}
Output:
First 30 triangular numbers:
  0   1   3   6  10  15
 21  28  36  45  55  66
 78  91 105 120 136 153
171 190 210 231 253 276
300 325 351 378 406 435

First 30 tetrahedral numbers:
   0    1    4   10   20   35
  56   84  120  165  220  286
 364  455  560  680  816  969
1140 1330 1540 1771 2024 2300
2600 2925 3276 3654 4060 4495

First 30 pentatopic numbers:
    0     1     5    15    35    70
  126   210   330   495   715  1001
 1365  1820  2380  3060  3876  4845
 5985  7315  8855 10626 12650 14950
17550 20475 23751 27405 31465 35960

First 30 12-simplex numbers:
         0          1         13         91        455       1820
      6188      18564      50388     125970     293930     646646
   1352078    2704156    5200300    9657700   17383860   30421755
  51895935   86493225  141120525  225792840  354817320  548354040
 834451800 1251677700 1852482996 2707475148 3910797436 5586853480

Roots of 7140:
  triangular-root: 119
 tetrahedral-root: 34
  pentatopic-root: 18.876646615928006607901783

Roots of 21408696:
  triangular-root: 6543
 tetrahedral-root: 503.56182697463651404819613
  pentatopic-root: 149.060947375265867484387575

Roots of 26728085384:
  triangular-root: 231205.405565255836957291031961
 tetrahedral-root: 5432
  pentatopic-root: 893.442456751684869888466212

Roots of 14545501785001:
  triangular-root: 5393607.158145172316497304724655
 tetrahedral-root: 44355.777384073256052620916903
  pentatopic-root: 4321

Wren

Library: Wren-fmt
Library: Wren-big
import "./fmt" for Fmt
import "./big" for BigRat

var t = List.filled(30, 0)
for (n in 1..29) t[n] = t[n-1] + n
System.print("The first 30 triangular numbers are:")
Fmt.tprint("$3d", t, 6)

for (n in 1..29) t[n] = t[n] + t[n-1]
System.print("\nThe first 30 tetrahedral numbers are:")
Fmt.tprint("$4d", t, 6)

for (n in 1..29) t[n] = t[n] + t[n-1]
System.print("\nThe first 30 pentatopic numbers are:")
Fmt.tprint("$5d", t, 6)

for (r in 5..12) {
    for (n in 1..29) t[n] = t[n] + t[n-1]
}
System.print("\nThe first 30 12-simplex numbers are:")
Fmt.tprint("$10d", t, 6)

var xs = [7140, 21408696, 26728085384, 14545501785001]
var digs = 16
for (x in xs) {
    var bx = BigRat.new(x)
    System.print("\nRoots of %(x):")
    var root = ((bx*8 + 1).sqrt(digs) - 1)/2
    Fmt.print("$14s: $s", "triangular", root.toDecimal(digs-5))

    var temp = (bx*bx*9 - BigRat.new(1, 27)).sqrt(digs)
    root = (bx*3 + temp).cbrt(digs) + (bx*3 - temp).cbrt(digs) - 1
    Fmt.print("$14s: $s", "tetrahedral", root.toDecimal(digs-5))

    root = (((bx*24 + 1).sqrt(digs)*4 + 5).sqrt(digs) - 3) / 2
    Fmt.print("$14s: $s", "pentatopic", root.toDecimal(digs-5))
}
Output:
The first 30 triangular numbers are:
  0   1   3   6  10  15 
 21  28  36  45  55  66 
 78  91 105 120 136 153 
171 190 210 231 253 276 
300 325 351 378 406 435 

The first 30 tetrahedral numbers are:
   0    1    4   10   20   35 
  56   84  120  165  220  286 
 364  455  560  680  816  969 
1140 1330 1540 1771 2024 2300 
2600 2925 3276 3654 4060 4495 

The first 30 pentatopic numbers are:
    0     1     5    15    35    70 
  126   210   330   495   715  1001 
 1365  1820  2380  3060  3876  4845 
 5985  7315  8855 10626 12650 14950 
17550 20475 23751 27405 31465 35960 

The first 30 12-simplex numbers are:
         0          1         13         91        455       1820 
      6188      18564      50388     125970     293930     646646 
   1352078    2704156    5200300    9657700   17383860   30421755 
  51895935   86493225  141120525  225792840  354817320  548354040 
 834451800 1251677700 1852482996 2707475148 3910797436 5586853480 

Roots of 7140:
    triangular: 119
   tetrahedral: 34.00000000000
    pentatopic: 18.87664661593

Roots of 21408696:
    triangular: 6543
   tetrahedral: 503.56182697464
    pentatopic: 149.06094737527

Roots of 26728085384:
    triangular: 231205.40556525584
   tetrahedral: 5432.00000000000
    pentatopic: 893.44245675168

Roots of 14545501785001:
    triangular: 5393607.15814517232
   tetrahedral: 44355.77738407326
    pentatopic: 4321