This is my response to the Perl Weekly Challenge #107.
I realised just before the launch this task was also part of the week 43 and contributed by Laurent Rosenfeld. It is too late to change now. Feel free to share your previous solutions if you took part in the week 43 already. I should have been more carefull, sorry.
The program from part 2 of my Olympic Numbers with Raku article looks like this:
File: selfdesc
#! /usr/bin/env raku
unit sub MAIN (UInt :$base = 10);
if $base == any(0,1,2,3,6) || $base > 39
{
say "Error";
}
elsif $base == 5
{
say "21200"; # Prevent "11100"
}
else
{
my $number = "{ ($base -4).base(36) }21" ~ "0" x ($base - 3);
$number.substr-rw(*-4,1) = 1;
say $number;
}
Follow the link above for a discussion of the code, and the result of running the program.
That was easy.
So let us have a go at something similarly named instead. Deceptive Numbers sound fun. (They are also called «Deceptive Non-Primes», but that is not as catchy a name.)
This is a sequence of values (integers), and we can use
gather
/take
to collect the values:
#! /usr/bin/env raku
unit sub MAIN ($count);
my $seq := gather
{
my $index = 3; # [1]
loop
{
unless $index.is-prime # [2]
{
take $index if (10 ** ($index -1)) % (9 * $index) == 1; # [3]
}
$index++;
}
}
say $seq[^$count];
[1] The article uses the term «odd prime», which means that we must skip 2 (witch is the one and only even prime).
[2] Skip primes. Note that we could have started with 1 in [1] because of this, but it does not really matter.
[3] The formulae is taken from The On-Line Encyclopedia of Integer Sequences.
See my Raku Gather,
I Take article or
docs.raku.org/syntax/gather take for more information about
gather
/take
.
Running it:
$ ./deceptive-numbers 3
(91 259 451)
$ ./deceptive-numbers 10
(91 259 451 481 703 1729 2821 2981 3367 4141)
$ ./deceptive-numbers 20
(91 259 451 481 703 1729 2821 2981 3367 4141 4187 5461 6533 6541 6601 7471 \
7777 8149 8401 8911)
We got the correct numbers.
package Calc;
use strict;
use warnings;
sub new { bless {}, shift; }
sub add { }
sub mul { }
sub div { }
1;
Output
BEGIN
mul
div
new
add
We can get a list of methods by calling the built-in .^methods
on an object
or the class itself:
#! /usr/bin/env raku
class Calc
{
has $.value; # [1]
has $.next is rw; # [2]
method add { … } # [3]
method mul { … }
method div { … }
}
.say for Calc.^methods;
[1] A read only attribute.
[2] A read write attribute.
[3] The three dots (...
) or the Unicode variant …
gives
a stubbed method. The code will compile, but will throw an error if we execute one
of them. (I could have used an empty body instead ({ }
), but stubbing
is useful when developing a class. If you forget to remove the dots, the program will
tell you (by dying) if you try to execute it.
Note that we do not have no declare a custom «new» method, as Raku provides one for us.
Raku has Metaobject protocol (MOP) with full introspection of the Raku object system. See docs.raku.org/language/mop for more information.
Running it:
$ ./list-methods
add # [1]
mul # [1]
div # [1]
value # [2]
next # [2]
Submethod+{is-hidden-from-backtrace}.new # [3]
[1] The first three are as expected.
[2] Oops. These are the attributes in the class. They show up here as Raku provides access methods for us automatically. We'll look into that later.
[3] This is the builtin «new» method.
The «new» method (in [3]) does not look very nice, but we can fix that by supplying our own version of the «new» method (so that it isn't inherited). We can get rid of the access methods (in [2]) by changing the attributes to private.
File: list-methods-new
#! /usr/bin/env raku
class Calc
{
has $!value; # [1]
has $!next;
method new { … } # [2]
method add { … }
method mul { … }
method div { … }
}
.say for Calc.^methods;
[1] A private attribute (with !
instead of .
after the sigil).
[2] A custom «new» method, replacing the built-in one.
Running it:
$ ./list-methods-new
new
add
mul
div
BUILDALL
The «BUILDALL» method is probably ok (as the challenge listed a «BEGIN» method for Perl).
And that's it.