by Arne Sommer

# Esthetic Sylvester with Raku

[192] Published 17. July 2022.

This is my response to The Weekly Challenge #173.

## Challenge #173.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 ```
File: esthetic-number ```#! /usr/bin/env raku unit sub MAIN (Int \$n where \$n > 0)); # [1] say + is-esthetic(\$n); # [2] sub is-esthetic (\$number) # [2a] { my @digits = \$n.comb; # [3] my \$current = @digits.shift; # [4] while @digits.elems # [5] { return False if all (\$current != @digits[0] + 1), (\$current != @digits[0] - 1); # [6] \$current = @digits.shift; # [7] } return True; # [8] } ```

[1] Ensure a positive integer.

[2] Print «1» if the number is esthetic, and «0» if not. I have delegated the computation to a procedure [2a] to make reuse easier. Note the Numeric Coercion Prefix Operator `+` used to get a numeric value instead of the `True`/`False` returned by the procedure.

See docs.raku.org/routine/+ for more information about the Numeric Coercion Prefix Operator `+`.

[3] Get the individual digits.

[4] Get the first digit.

[5] As long as there are more digits,

[6] The first `!=` checks that the current digit is not one less than the next one, and the second one that it is not one more than it. If both are true (set up with an `all` junction, we do not have an esthetic number (and returns `False`).

See docs.raku.org/routine/all for more information about the `all` Junction.

[7] Move along, one more digit.

[8] We have reached the end, without failing. Then we have an esthetic number.

Running it:

```\$ ./esthetic-number 5456 1 \$ ./esthetic-number 120 0 ```

Looking good.

Note that one-digit numbers are considered esthetic by my implementation:

```\$ ./esthetic-number 1 1 ```

## Challenge #173.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 16550664732451996419846819544443918001751315270637749784185138876653\ 5868639572406808911988131737645185443 ```

This sequence popped up in part 7 of my Centenary Sequences with Raku article, published in November 2020, as sequence #085:

```(my \$sum = 2, { my \$c = \$sum +1; \$sum *= \$c; \$c } ... Inf) # 085 ```

It was presented without explanation, but I'll do it this time:

```(my \$sum = 2, { my \$c = \$sum +1; \$sum *= \$c; \$c } ... Inf) # 1 ######## # 2 ############################### # 3 #### ```

[1] This (everything before the comma) is the first value in the sequence. We declare a variable `\$sum` which is local to the sequence. The result of the assignment is the value itself, which then is the first value.

[2] We set up a local variable `\$c`, and use that one to change the global (from the point of view of this block) `\$sum`. The generated value for the sequence is the last one in the block - which is the single `\$c`.

[3] This tells Raku to use the block to the left [2] to genereate values ad infinitum.

I used it like this:

```> say (my \$sum = 2, { my \$c = \$sum +1; \$sum *= \$c; \$c } ... Inf)[^8]; (2 3 7 43 1807 3263443 10650056950807 113423713055421844361000443) ```

Wrapping it up as a program is easy:

File: sylvesters-sequence ```#! /usr/bin/env raku unit sub MAIN (Int \$count where \$count > 0 = 10); my \$ss := (my \$sum = 2, { my \$c = \$sum +1; \$sum *= \$c; \$c } ... Inf); say \$ss[^\$count].join("\n"); # [1] ```

[1] The `join` adds a newline between each value, and the `say` adds one after the last one - giving the output as specified by the challenge.

Running it:

```\$ ./sylvesters-sequence 2 3 7 43 1807 3263443 10650056950807 113423713055421844361000443 12864938683278671740537145998360961546653259485195807 16550664732451996419846819544443918001751315270637749784185138876653\ 5868639572406808911988131737645185443 ```

Looking good.

```\$ ./sylvesters-sequence 11 2 3 7 43 1807 3263443 10650056950807 113423713055421844361000443 12864938683278671740537145998360961546653259485195807 16550664732451996419846819544443918001751315270637749784185138876653\ 5868639572406808911988131737645185443 27392450308603031423410234291674686281194364367580914627947367941608\ 692026226993634332118404582438634929548737283992369758487974306317\ 730580753883429460344956410077034761330476016739454649828385541500\ 213920807 ```

The number of digits in each value increases at an alarming rate, after the first three values. Here is a Sylvester length sequence, giving us the number of digits instead of the actual values:

File: sylvesters-length-sequence ```#! /usr/bin/env raku unit sub MAIN (Int \$count where \$count > 0 = 10); my \$ss := (my \$sum = 2, { my \$c = \$sum +1; \$sum *= \$c; \$c } ... Inf); say \$ss[^\$count].map( *.chars ).join(", "); # [1] ```

[1] Note the `map` we have inserted here, giving the number of characters (i.e. digits), instead of the actual value. Doing this in the sequence would require a major rewrite. (I have chosen to print a comma separated list this time, as the values are much smaller.)

Running it:

```\$ ./sylvesters-length-sequence 12 1, 1, 1, 2, 4, 7, 14, 27, 53, 105, 209, 417 ```

The pattern (from «4») seems to be «double the value and then subtract 1».

Generating some more values falsifies that assumption:

```\$ ./sylvesters-length-sequence 15 1, 1, 1, 2, 4, 7, 14, 27, 53, 105, 209, 417, 834, 1668, 3336 ```

And that's it.