Peter’s blog ✴ Week 173 ✴ 11 July 2022

THE WEEKLY CHALLENGE
Aesthetics and a fast-growing sequence

The Perl Camel

Task 2

Sylvester’s sequence

Write a script to generate first 10 members of Sylvester's sequence. For more information, please refer to the Wikipedia page.

Analysis

Sylvester the cat

I had rather hoped that this was discovered by the eponymous cat, but it seems that James Joseph Sylvester was responsible. The sequence starts with 2, 3, and each subsequent term is the product of all the preceding ones, plus one.

A little reflection reveals that:

  • This is going to get big as fast as a pumpkin
  • So we'd better resort to Math::BigInt

We can save microseconds by noting that term n really only depends on term n - 1. Specifically:

syl(n) = (syl(n - 1) - 1) * syl(n - 1) + 1

And once we have conquered the challenge of expressing that in BigInt-ian:

$sylvester[$j] = Math::BigInt->new(0)  # zero
  ->badd($sylvester[$j - 1])     # plus preceding term
  ->bsub(Math::BigInt->new(1))   # minus 1 
  ->bmul($sylvester[$j - 1])     # times preceding one
  ->badd(Math::BigInt->new(1));  # plus 1

... we have our solution.

We are asked for the first 10 terms, and the tenth turns out to be 1655066473245199641984681954444391800175131527063774978418 51388766535868639572406808911988131737645185443, which confirms the decision to use BigInt.

Perl Weekly’s review

from PW issue 573

I really enjoy the mention of eponymous cat. I am sure you will find it interesting too.

Script


#!/usr/bin/perl

# Peter Campbell Smith - 2022-07-11
# PWC 173 task 2

use v5.26;
use strict;
use warnings;
use utf8;
binmode(STDOUT, ':utf8');
use Math::BigInt;

my (@sylvester, $j);

# first 2 terms are given
$sylvester[0] = Math::BigInt->new(2);
$sylvester[1] = Math::BigInt->new(3);

# loop over 10 terms
for $j (0 .. 9) {
    if ($j > 1) {
        $sylvester[$j] = Math::BigInt->new(0)  # zero
            ->badd($sylvester[$j - 1])         # plus the preceding term
            ->bsub(Math::BigInt->new(1))       # minus 1 (to get product of all terms up to preceding one)
            ->bmul($sylvester[$j - 1])         # times the preceding one
            ->badd(Math::BigInt->new(1));      # plus 1
    }
    say qq[sylvester[$j] = ] . $sylvester[$j]->bstr();
}

17 lines of code

Output from script

sylvester[0] = 2
sylvester[1] = 3
sylvester[2] = 7
sylvester[3] = 43
sylvester[4] = 1807
sylvester[5] = 3263443
sylvester[6] = 10650056950807
sylvester[7] = 113423713055421844361000443
sylvester[8] = 12864938683278671740537145998360961546653259485195807
sylvester[9] =
   1655066473245199641984681954444391800175131527063774978418513887665
   35868639572406808911988131737645185443

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain