PWC #173
PWC #173
Challenge 1 (Esthetic numbers)
Esthetic numbers are numbers in which consecutive digits are either one less or one more than the (previous or next) other digit. For example, 5_654 is an esthetic number but 120 is not.
We are asked to find a function that tells us whether a particular input number is esthetic or no.
This seems like a good candidate for a regex solution, but I wound up just looping through the characters in the number (as a string) and checking if the next character was one more or less. If not, then it is not esthetic, otherwise it is. I also check that the input is numeric (otherwise not esthetic). In Perl and Raku, I check for and drop the "_" character used as a thousands separator. I have not considered single-digit numbers, the algorithm assumes the number is at least two digits (easy to fix, but I'll leave it). The internet tells me that single-digit numbers are esthetic by convention. My if condition is unnecessarily clunky, I check separately if the consecutive digits are 1 more or 1 less than each other, and then negate that. A better way is to just check if the absolute value of the difference is greater than 1.
My Perl 5, Raku and Julia scripts are all similar in their logic and even the clunky syntax. In Julia, I was more careful about explicit casting to string and back to Int. As usual, I have done the scripts in Julia too for benchmarking.
There is of course at least one (deceptively easy) regex-based solution, as demonstrated by another contributor, Philippe Bricout alias brxfork here. The insight is that it is easier and faster to look for non-esthetic numbers rather than esthetic ones. For example, if we match 1[^02] (1 followed by anything except 0 or 2), then we know we have a non-esthetic number and return false, and similarly for other digits. If we fail to find a non-esthetic number using this regex, then obviously we have an esthetic number.
Challenge 2 (Sylvester sequence)
The Sylvester sequence is one in which each term is the product of all the previous terms plus one, and the starting term indexed zero equals 2. Equivalently, we have the equation for the i'th term X[i] say:
X[i] = X[i-1]*(X[i-1]-1)+1
We are asked to find the first 10 terms
In Raku, this is a one-liner.
say (2, {$^x * ($^x-1)+1}...*).head(10)
In Perl 5 and Julia, I use a loop with similar logic. Start with 2 and calculate each term using the formula based on the previous term. Perl 5 uses scientific notation to print out the larger numbers, but otherwise all is similar. All three handle the very large integers with high speed. In Perl 5, I called PDL. PDL does not seem to support bigints. Of course, it's not necessary to use PDL, a regular Perl array would do fine.
Comments