Perl Weekly Challenge 173: Esthetic Number and Sylvester's Sequence
These are some answers to the Week 173 of the Perl Weekly Challenge organized by Mohammad S. Anwar.
Spoiler Alert: This weekly challenge deadline is due in a few of days from now (on July 17, 2022 at 23:59). This blog post offers some solutions to this challenge, please don’t read on if you intend to complete the challenge on your own.
Task 1: Esthetic Number
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
Esthetic Number in Raku
We write an is-esthetic
subroutine which splits the input number into an array of digits and checks, for each digit, whether the absolute value of its difference with the previous one is equal to 1. The subroutine returns False
is this value is not 1. If it loops through the end, it returns True.
sub is-esthetic ($n) {
my @d = $n.comb; # get an array of digits
return False if abs(@d[$_] - @d[$_-1]) != 1 for 1..@d.end;
return True;
}
for <5456 120 121 23456 2346 7654567 765467> -> $test {
say $test.fmt("%-9d"), is-esthetic($test) ?? "is esthetic" !! "is not esthetic";
}
This program displays the following output:
$ raku ./esthetic_nums.raku
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Perl
This is a port to Perl of the previous Raku program, with an is_esthetic
subroutine returning 0 (false value) if the absolute value of the difference between two adjacent digits is not equal to 1.
use strict;
use warnings;
use feature "say";
sub is_esthetic {
my @d = split //, shift; # get an array of digits
for my $i (1..$#d) {
return 0 if abs($d[$i] - $d[$i -1 ]) != 1;
}
return 1;
}
for my $test (qw<5456 120 121 23456 2346 7654567 765467>) {
say sprintf("%-9d", $test), is_esthetic($test) ? "is esthetic" : "is not esthetic";
}
This program displays the following output:
$ perl ./esthetic_nums.pl
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Julia
In Julia, you can use subscripts to access individual characters of a string:
julia> print("hello World"[5]) # Scala subscripts start at 1
o
You cannot do that in Perl and in Raku. Well, in Raku, you could implement your own postcircumfix [...]
operator like this:
multi sub postcircumfix:<[ ]> (Str $s, Int $n) {
substr-rw $s, $n, 1;
}
but it doesn’t seem to be worth the trouble for such a simple program.
Anyway since subscript can be used for that purpose in Scala, I decided that my program could easily traverse the string representation of the candidate number, without having to split it into an array of individual digits. All we need to do is to coerce the input number into a string.
function is_esthetic(num)
n = string(num)
for i in 2:length(n)
if abs(n[i] - n[i-1]) != 1
return false
end
end
return true
end
for test in [5456, 120, 121, 23456, 2346, 7654567, 765467]
println("$test\t", is_esthetic(test) ? "Esthetic" : "Non esthetic")
end
It may not be obvious, but there is quite a bit of magic going on in this line:
if abs(n[i] - n[i-1]) != 1
n[i]
and n[i+1]
don’t contain digits, but characters representing digits (ASCII representation). For example, if we are processing a '1'
character, we are processing ASCII char 49. So, perhaps, we should convert them to integers:
if abs(Int(n[i]) - Int(n[i-1])) != 1
Well, still not quite good. If the number being tested if 12, the line above would compare integers 49 (char ’1’
) and 50 (char ’2’
), not numbers 1 and 2. To really compare 1 and 2, we would have to subtract Int['0']
(48) from each term:
if abs((Int(n[i]) - Int('0')) - (Int(n[i-1] - Int('0'))) != 1
Of course, subtracting Int('0')
(48) from both terms of a subtraction is useless, as the result will be unchanged. But, more broadly, we don’t need to go through the trouble of casting the chars to ints, because Julia can easily compute the numerical difference between two characters. It even works with non-numerical characters such as letters:
julia> print('e' - 'c')
2
Output:
$ julia ./esthetic_nums.jl
5456 Esthetic
120 Non esthetic
121 Esthetic
23456 Esthetic
2346 Non esthetic
7654567 Esthetic
765467 Non esthetic
Esthetic Number in Python
In Python, you can also use subscripts to access individual characters of a string, so I chose to also traverse the string representation of the input integer. But it turned out to be a bit more complicated than in Julia. In Python, we need to cast the individual characters into integers to make the subtraction possible.
def is_esthetic(m):
n = str(m)
for i in range(1, len(n)):
if abs(int(n[i]) - int(n[i - 1 ])) != 1:
return False
return True
for test in [5456, 120, 121, 23456, 2346, 7654567, 765467]:
if is_esthetic(test):
print("{:<9d} is esthetic".format(test))
else:
print("{:<9d} is not esthetic".format(test))
Output:
$ python3 ./esthetic_nums.py
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Ruby
Like in Python, we need to cast characters to integers to make the subtraction possible in Ruby:
def is_esthetic(m)
n = m.to_s
for i in 1..(n.length - 1)
if (n[i].to_i - n[i-1].to_i).abs != 1
return false
end
end
return true
end
for test in [ 5456, 120, 121, 23456, 2346, 7654567, 765467]
printf "%-9d ", test
if is_esthetic(test)
print("is esthetic\n")
else
print("is not esthetic\n")
end
end
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Ring
Like in Julia, there is no need to cast characters to integers in Ring:
for test in [5456, 120, 121, 23456, 2346, 7654567, 765467]
see test
if is_esthetic(test)
see " is esthetic" + nl
else
see " is not esthetic" + nl
ok
next
func is_esthetic (num)
n = "" + num
for i = 2 to len(n)
if fabs(n[i] - n[i-1]) != 1
return false
ok
next
return true
Output:
$ ring ./esthetic_nums.ring
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Kotlin
Note that the subtraction n[i] - n[i-1]
in the is_esthetic
function works fine here because a subtraction on two Char
values in Kotlin returns an Int
value, so that the comments made on the Julia implementation essentially also apply to Kotlin.
import kotlin.math.abs
fun is_esthetic(num: Int): Boolean {
val n = num.toString()
for (i in 1..n.length - 1) {
if (abs(n[i] - n[i-1]) != 1) {
return false
}
}
return true
}
fun main() {
for (test in arrayOf(5456, 120, 121, 23456, 2346, 7654567, 765467)) {
if (is_esthetic(test)) {
println("$test is esthetic")
} else {
println("$test is not esthetic")
}
}
}
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Go
package main
import (
"fmt"
"strconv"
)
func is_esthetic(n int) bool {
s := strconv.Itoa(n)
for i := 1; i < len(s); i++ {
if s[i]-s[i-1] != 1 && s[i-1]-s[i] != 1 {
return false
}
}
return true
}
func main() {
tests := []int{5456, 120, 121, 23456, 2346, 7654567, 765467}
for _, test := range tests {
if is_esthetic(test) {
fmt.Printf("%-9d is esthetic\n", test)
} else {
fmt.Printf("%-9d is not esthetic\n", test)
}
}
}
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in D
import std.stdio;
import std.math;
import std.conv;
bool is_esthetic(int num) {
auto s = to!string(num, 10);
foreach (i; 1 .. s.length) {
if (abs(s[i] - s[i-1]) != 1) return false;
}
return true;
}
void main() {
int[] tests = [ 5456, 120, 121, 23456, 2346, 7654567, 765467 ];
foreach(test; tests) {
printf("%-9d ", test);
if (is_esthetic(test)) {
writeln("is esthetic");
} else {
writeln("is not esthetic");
}
}
}
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Nim
import strutils
import std/strformat
proc is_esthetic(num: int): bool =
let n = intToStr(num)
for i in 1..len(n)-1:
if abs(int(n[i]) - int(n[i-1])) != 1:
return false
return true
for test in [5456, 120, 121, 23456, 2346, 7654567, 765467]:
if is_esthetic(test):
echo fmt("{test:<9}"), " is esthetic"
else:
echo fmt("{test:<9}"), " is not esthetic"
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Rust
Sometimes, a strict typing system can be a straight jacket. Rust’s typing system seems to be such. I was’t able to find a way to subtract characters and take the absolute value of the result. So I had to use two separate conditions: if n[i] != n[i-1] + 1 && n[i-1] != n[i] + 1 ...
fn is_esthetic(num: i32) -> bool {
let n = num.to_string();
for i in 1..n.len() {
if n.as_bytes()[i] != n.as_bytes()[i-1] + 1 &&
n.as_bytes()[i-1] != n.as_bytes()[i] + 1 {
return false
}
}
return true
}
fn main() {
for test in [5456, 120, 121, 23456, 2346, 7654567, 765467] {
println!("{} -> {}", test, if is_esthetic (test) { " is esthetic"} else { " is not esthetic"});
}
}
Output:
5456 -> is esthetic
120 -> is not esthetic
121 -> is esthetic
23456 -> is esthetic
2346 -> is not esthetic
7654567 -> is esthetic
765467 -> is not esthetic
Esthetic Number in Scala
object esthetic extends App {
def is_esthetic(num: Int): Boolean = {
val digits = num.toString.split("")
for (i <- 1 to (digits.size) - 1) {
if ((digits(i).toInt - digits(i-1).toInt).abs != 1) {
return false
}
}
return true
}
val tests = List(5456, 120, 121, 23456, 2346, 7654567, 765467)
for (test <- tests) {
if (is_esthetic(test)) {
println(s"$test is esthetic")
} else {
println(s"$test is not esthetic")
}
}
}
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Esthetic Number in Java
I’m not a great fan of Java, because I find it too verbose. But it is good, some times, to take a fresh look at things.
import java.lang.Math;
public class EstheticNumber {
public static void main(String[] args) {
Integer[] tests = {5456, 120, 121, 23456, 2346, 7654567, 765467};
for (int i = 0; i <= 6; i++) {
if (is_esthetic(tests[i])) {
System.out.printf("%-9d is esthetic\n", tests[i]);
} else {
System.out.printf("%-9d is not esthetic\n", tests[i]);
}
}
}
public static boolean is_esthetic(int n) {
String s = Integer.toString(n);
for (int i = 1; i < s.length(); i++ ) {
if (Math.abs((int)(s.charAt(i)) - (int)(s.charAt(i-1))) != 1) {
return false;
}
}
return true;
}
}
Output:
5456 is esthetic
120 is not esthetic
121 is esthetic
23456 is esthetic
2346 is not esthetic
7654567 is esthetic
765467 is not esthetic
Task 2: Sylvester’s Sequence
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
Each number in the sequence is the product of all previous numbers of the sequence plus 1.
The only potential difficulty with this problem is that we’re dealing with very large integers so that, for some programming languages at least, we may encounter an integer overflow error (or values may be converted to floats, with a resulting loss of precision).
Sylvester’s Sequence in Raku
In Raku, Int
objects store integral numbers of arbitrary size. So we don’t have to worry about very large integers.
We start with a direct implementation of the definition. We store the sequence in the @s
array. To get a new number, we simply compute the product of all items of the @s
array (using the [*]
meta-operator) and add it to the array.
my @s = 2;
while @s.elems < 10 {
push @s, 1 + [*] @s;
}
.say for @s;
This program displays the following output:
$ raku ./sylvester.raku
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
The program runs very fast, but is not as efficient as it could be because we are performing some of the multiplications many times. When computing @s[$n+1]
, we know that @s[$n]
contains the product of all values between @s[0]
and @s[$n-1]
plus 1. Therefore, the n + 1
item of the sequence can be defined recursively as @s[$n] * (@s[$n] - 1) + 1
, so that we can perform only one multiplication each time. This can lead to the following modified implementation:
my @n = 2;
push @n, @n[*-1] * (@n[*-1] - 1) + 1 for 1..^10;
.say for @n;
This program displays the same output as above:
$ raku ./sylvester2.raku
2
3
7
43
1807
(lines omitted for brevity)
Sylvester’s Sequence in Perl
In Perl, scalars cannot contain such large integers. But we can use the use BigInt;
pragma to convert all numeric literals to Math::BigInt
, which can store arbitrarily large integers.
To port the first raku program above to Perl, we implement a prod
subroutine that computes the product of all items of its input.
use strict;
use warnings;
use feature "say";
use bigint;
sub prod {
my $prod = 1;
$prod *= $_ for @_;
return $prod;
}
my @s = (2);
while (@s < 10) {
push @s, 1 + prod @s;
}
say for @s;
This program displays the following output:
$ perl ./sylvester.pl
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
We can avoid the prod
subroutine if we use the method of the second Raku program above:
use strict;
use warnings;
use feature "say";
use bigint;
my @s = (2);
push @s, $s[-1] * ($s[-1] - 1) + 1 for 1..9;
say for @s;
This program displays the same output:
$ perl ./sylvester2.pl
2
3
7
43
1807
(lines omitted for brevity)
Sylvester’s Sequence in bc
The Unix bc
utility is an arbitrary precision calculator language, so it is tempting to use it for a problem in which the only potential difficulty is the use of very large integers. However, bc
’s arrays lack many of the cool features of more modern languages. We will implement the second method above without using any array (printing the values as we compute them).
n = 2
print n, "\n"
count = 1
while (count < 10) {
n = (n - 1) * n + 1
print n, "\n"
count += 1
}
quit
This script displays the following output:
$ bc ./sylvester.bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
16550664732451996419846819544443918001751315270637749784185138876653\
5868639572406808911988131737645185443
One last little problem here is that bc cannot print numbers larger than 70 digits on the same line, so that the last Sylvester number above is cut over two lines. We can pipe the bc output through a Perl one-line filter (or some other utility) to reformat properly the faulty line:
$ bc sylvester.bc | perl -pe 's/\\\s//'
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Another way is to set the BC_LINE_LENGTH
environment variable to 0:
$ BC_LINE_LENGTH=0 bc sylvester.bc
bc 1.06.95
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'.
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in dc
The Unix dc
utility is also an arbitrary precision calculator language, so it is tempting to use it for a problem in which the only potential difficulty is the use of very large integers. In fact, bc used to be a standard infix front-end to the dc reverse Polish notation.
This is a dc program to display the first 10 elements of the Sylvester’s sequence:
2snlnp9sc[1-ln*1+psnlnlc1-sc0lc>m]dsmx
You can run it as follows:
$ echo '2snlnp9sc[1-ln*1+psnlnlc1-sc0lc>m]dsmx
' | DC_LINE_LENGTH=0 dc
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
OK, I must admit that I golfed it. I usually try to use concise syntax, but don’t commonly golf my solutions. Here, I think that I probably deserve an award for the shortest and most obfuscated golf piece for that problem.
This is now a much more readable version of the same solution:
2sn # push 2 on the stack, pop 2 off the top of the stack and store it into register n
lnp # copy the value back on the stack and print it
9sc # give counter c an initial value of 9
[ # start of macro
1- # subtract 1 from stack (value n-1)
ln # load n to stack
*1+p # compute product n * n-1, add 1 and print
sn # pop new value and store it in register n
ln # copy new value in n to stack
lc # copy counter to stack
1- # decrement counter (subtract 1 from c)
sc # store decremented counter in c
0 lc # store 0 and counter on stack
>m # compare counter to 0 and, if c > 0, run recursively macro in m
] # end of macro
d # duplicate macro
sm # store macro in register m
x # execute first iteration of macro
Understanding the solution in details would require a lot more explanations than what I can provide here. You are kindly invited to read this other blog post where I describe in detail how I solved the problem in dc.
Sylvester’s Sequence in Julia
With regular integers, we obtain totally wrong results, including negative integers and so forth. All we need to do to fix that problem is to declare our initial variable as a BigInt
:
s = BigInt(2)
println(s)
for i in 1:9
s = s * (s - 1) + 1
println(s)
end
Output:
$ julia ./sylvester.jl
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Python
Recent versions of Python automatically switch to big integers when needed:
s = [2];
for i in range(9):
s.append(s[-1] * (s[-1] - 1) + 1)
for j in s:
print(j)
Output:
$ python3 sylvester.py
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Ruby
# Ruby automatically switches to Bignum when needed
s = 2
print("#{s}\n")
for i in 1..9
s = s * (s - 1) + 1
print("#{s}\n")
end
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Ring
As far as I can tell, Ring doesn’t have a BigNum package. But Ring gracefully switches to floating point arithmetics and thus produces fairly decent approximations of the expected result.
s = 2;
see s + nl
for i = 1 to 9
s = s * (s - 1) + 1
see s + nl
next
Output:
$ ring ./sylvester.ring
2
3
7
43
1807
3263443
10650056950807
113423713055421845118910464.00
12864938683278672079501004830742670366487445279604736.00
1.655066473245199625930595525909356695752320791312711997146979916612453687017861571473280717e+104
The three last Sylvester numbers above are computed with floating point arithmetics. As you can see if you compare with the results obtained with other languages above, only the first 16th to 17th digits are accurate.
Sylvester Sequence in Scala
Like in Julia, we only need to declare our initial variable as a BigInt
to get the correct results in Scala:
object sylvester extends App {
var n = BigInt(2)
println(n)
for (i <- 1 to 9) {
n = n * (n - 1) + 1
println(n)
}
}
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Kotlin
In Kotlin, we import the java java.math.BigInteger
library. Note that it doesn’t know how to mix BigInteger
numbers with standard integers in computations, so we need to create one
, a BigInteger
for 1.
import java.math.BigInteger
fun main () {
var n = BigInteger("2")
val one = BigInteger("1")
for (i in 1..9) {
n = n * (n - one) + one
println(n)
}
}
Output:
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in D
import std.stdio;
import std.bigint;
void main() {
BigInt s = "2";
writeln(s);
for (int i = 1; i <= 9; i++) {
s = s * (s - 1) + 1;
writeln(s);
}
}
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Lua
I did not succeed to use the library for large integers. Perhaps my Lua installation is faulty, or I missed something else. I still want to show the result to illustrate how wrong a program can go in the event of an integer overflow not properly managed. We’ve seen before that Ring (for example) automatically switches to floats and provides results accurate to the first 16 decimal places. In Lua, this goes horribly wrong, and displays even negative integers.
-- Does not work properly
s = 2
print(s)
for i = 1, 9 do
s = s * (s - 1) + 1
print(s)
end
Output:
2
3
7
43
1807
3263443
10650056950807
-3591524960174918149
-8362769992138052065
4108952388197251491
Sylvester’s Sequence in Go
This works properly, but the method-invocation syntax for using big integers in Go is just plainly horrible and very difficult to use. I expected better from one of the world’s largest and wealthiest corporations and some legendary computer scientists, especially when it is claimed that Go was designed to be simple. OK, I must admit that it is still simpler than dc (see above), but dc was designed and written almost half a century ago.
// Go big int syntax really sucks
package main
import (
"fmt"
"math/big"
)
func main() {
s := big.NewInt(2)
fmt.Println(0, ": ", s)
one := big.NewInt(1)
for i := 1; i <= 9; i++ {
s.Add(new(big.Int).Mul(s, s), new(big.Int).Sub(one, s))
fmt.Println(i, ": ", s)
}
}
Output:
0 : 2
1 : 3
2 : 7
3 : 43
4 : 1807
5 : 3263443
6 : 10650056950807
7 : 113423713055421844361000443
8 : 12864938683278671740537145998360961546653259485195807
9 : 165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Nim
import bigints
var s = 2.initBigInt
echo s
for i in 1..9:
s = s * (s - 1) + 1
echo s
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Dart
Like in Kotlin, BigInt
objects don’t mix in properly with regular integers in Dart. So we need to declare a one
BigInt object for integer 1.
void main() { var s = BigInt.from(2); print(s); var one = BigInt.from(1); for (int i = 1; i <= 9; i++) { s = s * (s - one) + one; print(s); } }
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in JavaScript
Here, again, we need to declare a one
BigInt
object for integer 1.
let s = BigInt (2)
let one = BigInt (1)
console.log(s + " ");
for (let i = 1; i <= 9; i++) {
s = s * (s - one) + one
console.log(s + " ");
}
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in TCL
TCL natively supports arbitrarily large integers.
set s 2
puts $s
for {set i 1} {$i <= 9} {incr i} {
set s [expr ($s * ($s - 1) + 1)]
puts $s
}
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Sylvester’s Sequence in Java
I said before that I found Java to be a bit too verbose. If you don’t know what I mean, just compare the Java solution below with the TCL solution above.
import java.math.BigInteger;
public class Sylvester {
public static void main(String[] args) {
BigInteger n = BigInteger.valueOf(2);
System.out.printf("%s\n", n);
BigInteger one = BigInteger.valueOf(1);
for (int i = 1; i <= 9; i++) {
n = (n.multiply(n.subtract(one))).add(one);
System.out.printf("%s\n", n);
}
}
}
Output:
2
3
7
43
1807
3263443
10650056950807
113423713055421844361000443
12864938683278671740537145998360961546653259485195807
165506647324519964198468195444439180017513152706377497841851388766535868639572406808911988131737645185443
Wrapping up
The next week Perl Weekly Challenge will start soon. If you want to participate in this challenge, please check https://perlweeklychallenge.org/ and make sure you answer the challenge before 23:59 BST (British summer time) on July 24, 2022. And, please, also spread the word about the Perl Weekly Challenge if you can.
Leave a comment