Riordan numbers

Revision as of 17:34, 20 August 2022 by Tigerofdarkness (talk | contribs) (Added Algol 68)

Riordan numbers show up in several places in set theory. They are closely related to Motzkin numbers, and may be used to derive them.

Riordan 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.

Riordan numbers comprise the sequence a where:

   a(0) = 1, a(1) = 0, for subsequent terms, a(n) = (n-1)*(2*a(n-1) + 3*a(n-2))/(n+1)

There are other generating functions, and you are free to use one most convenient for your language.


Task
  • Find and display the first 32 Riordan numbers.


Stretch
  • Find and display the digit count of the 1,000th Riordan number.
  • Find and display the digit count of the 10,000th Riordan number.


See also



ALGOL 68

Works with: ALGOL 68G version Any - tested with release 2.8.3.win32 and 3.0.3

Uses ALGOL 68G's LONG LONG INT which has programmer-specifiable precision. ALGOL 68G version 3 issues a warning that precision 5000 will impact performance but it still executes this program somewhat faster than version 2 does. <lang algol68>BEGIN # find some Riordan numbers #

   # returns a table of the Riordan numbers 0 .. n #
   OP   RIORDAN = ( INT n )[]LONG INT:
        BEGIN
           [ 0 : n ]LONG INT a;
           IF n >= 0 THEN
               a[ 0 ] := 1;
               IF n >= 1 THEN
                   a[ 1 ] := 0;
                   FOR i FROM 2 TO UPB a DO
                       a[ i ] := ( ( i - 1 )
                                 * ( ( 2 * a[ i - 1 ] )
                                   + ( 3 * a[ i - 2 ] )
                                   )
                                 )
                            OVER ( i + 1 )
                   OD
               FI
           FI;
           a
        END # RIORDAN # ;
   # returns a string representation of n with commas                       #
   PROC commatise = ( STRING unformatted )STRING:
        BEGIN
           STRING result      := "";
           INT    ch count    := 0;
           FOR c FROM UPB unformatted BY -1 TO LWB unformatted DO
               IF  ch count <= 2 THEN
                   ch count +:= 1
               ELSE
                   ch count  := 1;
                   IF unformatted[ c ] = " " THEN " " ELSE "," FI +=: result
               FI;
               unformatted[ c ] +=: result
           OD;
           result
        END; # commatise #
   # returns the length of s                                                #
   OP LENGTH = ( STRING s )INT: ( UPB s - LWB s ) + 1;
   BEGIN # show some Riordann numbers                                       #
       []LONG INT r = RIORDAN 31;
       INT shown := 0;
       FOR i FROM LWB r TO UPB r DO
           print( ( commatise( whole( r[ i ], -15 ) ) ) );
           IF ( shown +:= 1 ) = 4 THEN
               print( ( newline ) );
               shown := 0
           FI
       OD
   END;
   BEGIN # calculate the length of the 1 000th and 10 000th Riordan numbers #
       PR precision 5000 PR # allow up to 5 000 digits for LONG LONG INT    #
       LONG LONG INT r2 := -1, r1 := 1, r := 0;
       print( ( newline ) );
       FOR i FROM 2 TO 9 999 DO
           r2 := r1;
           r1 := r;
           r := ( ( i - 1 )
                * ( ( 2 * r1 )
                  + ( 3 * r2 )
                  )
                )
             OVER ( i + 1 );
           IF i = 999 OR i = 9 999 THEN
               STRING rs = whole( r, 0 )[ @ 1 ];
               print( ( "The ", whole( i + 1, -6 ), "th number is: "
                      , rs[ 1 : 20 ], "...", rs[ LENGTH rs - 19 : ]
                      , " with ", whole( LENGTH rs, -5 ), " digits"
                      , newline
                      )
                    )
           FI
       OD
   END

END</lang>

Output:
                  1                  0                  1                  1
                  3                  6                 15                 36
                 91                232                603              1,585
              4,213             11,298             30,537             83,097
            227,475            625,992          1,730,787          4,805,595
         13,393,689         37,458,330        105,089,229        295,673,994
        834,086,421      2,358,641,376      6,684,761,125     18,985,057,351
     54,022,715,451    154,000,562,758    439,742,222,071  1,257,643,249,140

The   1000th number is: 51077756867821111314...79942013897484633052 with   472 digits
The  10000th number is: 19927418577260688844...71395322020211157137 with  4765 digits

F#

<lang fsharp> // Riordan numbers. Nigel Galloway: August 19th., 2022 let r()=seq{yield 1I; yield 0I; yield! Seq.unfold(fun(n,n1,n2)->let r=(n-1I)*(2I*n1+3I*n2)/(n+1I) in Some(r,(n+1I,r,n1)))(2I,0I,1I)} let n=r()|>Seq.take 10000|>Array.ofSeq in n|>Array.take 32|>Seq.iter(printf "%A "); printfn "\nr[999] has %d digits\nr[9999] has %d digits" ((string n.[999]).Length) ((string n.[9999]).Length) </lang>

Output:
1 0 1 1 3 6 15 36 91 232 603 1585 4213 11298 30537 83097 227475 625992 1730787 4805595 13393689 37458330 105089229 95673994 834086421 2358641376 6684761125 18985057351 54022715451 154000562758 439742222071 1257643249140
r[999] has 472 digits
r[9999] has 4765 digits

J

Sequence extender:<lang J>riordanext=: (, (<: % >:)@# * 3 2 +/ .* _2&{.)</lang> Task example:<lang J> riordanext^:(30) 1x 0 1 0 1 1 3 6 15 36 91 232 603 1585 4213 11298 30537 83097 227475 625992 1730787 4805595 13393689 37458330 105089229 295673994 834086421 2358641376 6684761125 18985057351 54022715451 154000562758 439742222071 1257643249140</lang>Stretch:<lang J> #":(1e3-1){riordanext^:(1e3) x:1 0 472

  #":(1e4-1){riordanext^:(1e4) x:1 0

4765</lang>

Phix

with javascript_semantics
requires("1.0.2") -- mpz_get_str(comma_fill) was not working [!!!]
include mpfr.e
constant limit = 10000
sequence a = {mpz_init(1),mpz_init(0)}
for n=2 to limit do
    mpz an = mpz_init()
    mpz_mul_si(an,a[n],2)
    mpz_addmul_si(an,a[n-1],3)
    mpz_mul_si(an,an,n-1)
    assert(mpz_fdiv_q_ui(an,an,n+1)=0)
    a &= an
end for
printf(1,"First 32 Riordan numbers:\n%s\n",
 {join_by(apply(true,mpz_get_str,{a[1..32],10,true}),1,4," ",fmt:="%17s")})
for i in {1e3, 1e4} do
    printf(1,"The %6s: %s\n", {ordinal(i), mpz_get_short_str(a[i])})
end for
Output:
First 32 Riordan numbers:
                1                 0                 1                 1
                3                 6                15                36
               91               232               603             1,585
            4,213            11,298            30,537            83,097
          227,475           625,992         1,730,787         4,805,595
       13,393,689        37,458,330       105,089,229       295,673,994
      834,086,421     2,358,641,376     6,684,761,125    18,985,057,351
   54,022,715,451   154,000,562,758   439,742,222,071 1,257,643,249,140

The one thousandth: 51077756867821111314...79942013897484633052 (472 digits)
The ten thousandth: 19927418577260688844...71395322020211157137 (4,765 digits)

Raku

<lang perl6>use Lingua::EN::Numbers;

my @riordan = 1, 0, { state $n = 1; (++$n - 1) / ($n + 1) × (3 × $^a + 2 × $^b) } … *;

my $upto = 32; say "First {$upto.&cardinal} Riordan numbers:\n" ~ @riordan[^$upto]».&comma».fmt("%17s").batch(4).join("\n") ~ "\n";

sub abr ($_) { .chars < 41 ?? $_ !! .substr(0,20) ~ '..' ~ .substr(*-20) ~ " ({.chars} digits)" }

say "The {.Int.&ordinal}: " ~ abr @riordan[$_ - 1] for 1e3, 1e4</lang>

Output:
First thirty-two Riordan numbers:
                1                 0                 1                 1
                3                 6                15                36
               91               232               603             1,585
            4,213            11,298            30,537            83,097
          227,475           625,992         1,730,787         4,805,595
       13,393,689        37,458,330       105,089,229       295,673,994
      834,086,421     2,358,641,376     6,684,761,125    18,985,057,351
   54,022,715,451   154,000,562,758   439,742,222,071 1,257,643,249,140

The one thousandth: 51077756867821111314..79942013897484633052 (472 digits)
The ten thousandth: 19927418577260688844..71395322020211157137 (4765 digits)

Wren

Library: Wren-gmp
Library: Wren-fmt

<lang ecmascript>import "./gmp" for Mpz import "./fmt" for Fmt

var limit = 10000 var a = List.filled(limit, null) a[0] = Mpz.one a[1] = Mpz.zero for (n in 2...limit) {

   a[n] = (a[n-1] * 2 + a[n-2] * 3) * (n-1) / (n+1)

} System.print("First 32 Riordan numbers:") Fmt.tprint("$,17i", a[0..31], 4) System.print() for (i in [1e3, 1e4]) {

  Fmt.print("$,8r: $20a ($,d digits)", i, a[i-1], a[i-1].toString.count)

}</lang>

Output:
First 32 Riordan numbers:
                1                 0                 1                 1 
                3                 6                15                36 
               91               232               603             1,585 
            4,213            11,298            30,537            83,097 
          227,475           625,992         1,730,787         4,805,595 
       13,393,689        37,458,330       105,089,229       295,673,994 
      834,086,421     2,358,641,376     6,684,761,125    18,985,057,351 
   54,022,715,451   154,000,562,758   439,742,222,071 1,257,643,249,140 

 1,000th: 51077756867821111314...79942013897484633052 (472 digits)
10,000th: 19927418577260688844...71395322020211157137 (4,765 digits)