Perl Weekly Challenge 173.

My solutions (task 1 and task 2 ) to the The Weekly Challenge - 173.

Task 1: Esthetic Number

Submitted by: Mohammad S Anwar
You are given a positive integer, $n.

Write a script to find out if the given number is Esthetic
Number.


An esthetic number is a positive integer where every adjacent
digit differs from its neighbour by 1.


For example,

5456 is an esthetic number as |5 - 4| = |4 - 5| = |5 - 6| = 1
120 is not an esthetic numner as |1 - 2| != |2 - 0| != 1

I use List::Util to check that all pairs of adjacent digits differ by ±1. This yields a simple oneliner.

perl -MList::Util=all -E 'foreach(@ARGV){($f,@a)=split ""; say "$_ ",
((all{($f,$t)=($_,abs($_-$f)==1); $t}(@a))? "is":"is not"), " an esthetic number"}
' 5456 120

Results:

5456 is an esthetic number
120 is not an esthetic number

This code fails when given some strings that are not quite numbers, as

perl -MList::Util=all -E 'foreach(@ARGV){($f,@a)=split ""; say "$_ ",
((all{($f,$t)=($_,abs($_-$f)==1); $t}(@a))? "is":"is not"), " an esthetic number"}
' a1b1

since, according to Perl, “a”-1==-1, 1-“b”==1, etc. Thus, in the full code I have to be more careful.

The full code is:

 1  # Perl weekly challenge 173
 2  # Task 1: Esthetic number
 3  #
 4  # See https://wlmb.github.io/2022/07/11/PWC173/#task-1-esthetic-number
 5  use v5.36;
 6  use List::Util qw(all);
 7  say("Usage: ./ch-1.pl N1 [N2...]\nto check if N1, N2... are esthetic numbers"), exit
 8      unless @ARGV;
 9  foreach(@ARGV){
10      s/^\s*\+\s*//;  # remove leading +, if present
11      say("Error: $_ is not a positive number"), next unless $_=~/^\d+$/;
12      my ($current,@rest)=split "";
13      my $test;
14      say "$_ ", (
15          (all {($current,$test)=($_, abs($_-$current)==1); $test}(@rest))
16          ? "is"
17          : "is not"
18          ), " an esthetic number";
19  }

Examples:

./ch-1.pl 5456 120

Results:

5456 is an esthetic number
120 is not an esthetic number

Other examples:

./ch-1.pl -123  +123 +125 +a1b1

Results:

Error: -123 is not a positive number
123 is an esthetic number
125 is not an esthetic number
Error: a1b1 is not a positive number

Task 2: Sylvester’s sequence

Submitted by: Mohammad S Anwar
Write a script to generate first 10 members of Sylvester's
sequence. For more informations, please refer to the wikipedia
page.


Output
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443

The n+1-th term Sn+1 in Sylvester’s sequence is the product of all the previous S1…Sn terms plus one. As Sn=S1×S2×…Sn-1+1 and Sn+1=S1×S2×…Sn-1×…Sn+1, we may write $Sn+1=Sn×(Sn-1)+1, so it is enough to keep the last result. This leads to a very simple one-liner:

perl -Mbigint -E '$s=2; say $s; say $s=$s*($s-1)+1 foreach(1..(shift)-1);' 10

Results:

2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443

I had to use bigint, as the Sylverster numbers diverge double-exponentially. The full code is almost identical:

 1  # Perl weekly challenge 173
 2  # Task 2: Sylverster's sequence
 3  #
 4  # See https://wlmb.github.io/2022/07/11/PWC173/#task-2-sylvesters-sequence
 5  use v5.36;
 6  use bigint;
 7  say("Usage: ./ch-2.pl N\nto print the first N numbers of Sylvester's sequence"), exit
 8      unless @ARGV;
 9  my $N=shift;
10  die "$N should be positive" unless $N>0;
11  my $s=2;
12  say "The first $N Sylvester's numbers are\n$s";
13  say $s=$s*($s-1)+1 foreach(1..$N-1);

Example:

./ch-2.pl 10

Results:

The first 10 Sylvester's numbers are
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443

A nice property of Sylvester’s sequence is that it yields the series of the type 1/n1+1/n2+1/n3… with ni integers, that converges the fastest towards 1, without actually arriving, starting from 1/2. Indeed, if you want to add something to 1/2 to arrive at 1, you would choose 1/2. But if instead you want to get as close as possible without arriving, you would add the smallest possible number to the denominator, 1, and then add 1/3. If now you want to add something to 1/2+1/3=5/6 to arrive at 1 you would choose 1/6, so if you want to get as close as possible without arriving you would add instead 1/7. As 1/2+1/3+1/7=(21+14+6)/42=41/42, the next number to add would be 1/43. It turns out that 1-(1/S1+1/S2+1/S3…+1/Sn)=1/(Sn+1-1) so it goes to zero double-exponentially. The first residues are

0.5
0.166666666667
0.0238095238095
5.53709856035e-4
3.06424934165e-7
9.38962115057e-14
8.81649853514e-27
Written on July 11, 2022