with Raku

This is my response to The Weekly Challenge #176.

Write a script to find the smallest positive integer

For example, the integers

`x`

such that
`x, 2x, 3x, 4x, 5x`

and `6x`

are permuted multiples of each other.
For example, the integers

`125874`

and `251748`

are permutated
multiples of each other as
251784 = 2 x 125874
and also both have the same digits but in different order.

Output
142857

We could just go with `my $pmt = (1..Inf).grep: *.&is-pm`

(and implement the
`is-pm`

function), but we can narrow down the possible numbers quite a lot.

The permuted multiples of the number have the same number of digits as the original number (as they must have the same individual digits). It follows from this that 6 times the original number cannot lead to a number with additional digits. The only leading digit allowed is 1 (as 1x6 = 6. 2 gives 2x6 = 12 - which has two digits). This is shown as A and B in this illustration:

Note that a leading «17» (and «18» and «19») will also give an additional digit (shown as C in the illustration), but this does not lead to so many values to discard as the first digit rule (discard anything but «1»).

Off we go.

File: permuted-multiples#! /usr/bin/env raku
unit sub MAIN (Int $count where $count > 0 = 1); # [1]
my $ptm := (^Inf).map({ "1$_" }).grep( *.&is-pm ); # [2]
say $ptm[^$count].join(", ");
sub is-pm ($number) # [3]
{
my $n = $number.comb.sort.join; # [4]
my $n2 = ($number * 2).comb.sort.join; # [5]
my $n3 = ($number * 3).comb.sort.join; # [5]
my $n4 = ($number * 4).comb.sort.join; # [5]
my $n5 = ($number * 5).comb.sort.join; # [5]
my $n6 = ($number * 6).comb.sort.join; # [5]
return $n eq $n2 eq $n3 eq $n3 eq $n4 eq $n5 eq $n6; # [6]
}

[1] Print the very first match, unless another number is specified.

[2] `^Inf`

gives the integer sequence 0,1,2,... . We kan skip integers
starting with any other digit than 1, and using `map`

to add a leading 1
to the values in the sequence does that nicely.

[3] Check if the number is a permuted multiple.

[4] Comparing numbers for the same digits can be done by transforming them to a canonical form (i.e. sorted), before the comparison. Then they would be the same.

[5] Compute the 2x, 3x, 4x and 5x. Then transform them to canonical form.

[6] We have a Permuted Multiple if all the canonical forms are identical.

Running it:

$ ./permuted-multiples
142857

Looking good.

More values?

$ ./permuted-multiples 3
142857, 1428570, 1429857

But we have a problem.

The algorithm added a leading «1» before the value it got from the sequence `^Inf`

.
The sequence gives us the values 0, 1, 2, and so on. The problem is that we have missed quite a
few numbers, e.g. 100, 101, 102, 1000, 1001, 1010. (Actually every integer where the second
digit is «0», except the number «10».)

So much for clever optimisation...

File: permuted-multiples-fixed```
#! /usr/bin/env raku
unit sub MAIN (Int $count where $count > 0 = 1);
my $ptm := (^Inf).grep({ $_.starts-with('1') && $_.&is-pm }); # [1]
say $ptm[^$count].join(", ");
sub is-pm ($number)
{
my $n = $number.comb.sort.join;
my $n2 = ($number * 2).comb.sort.join;
my $n3 = ($number * 3).comb.sort.join;
my $n4 = ($number * 4).comb.sort.join;
my $n5 = ($number * 5).comb.sort.join;
my $n6 = ($number * 6).comb.sort.join;
return $n eq $n2 eq $n3 eq $n3 eq $n4 eq $n5 eq $n6;
}
```

[1] Done right, this time. Note the use of `starts-with`

instead of
a (slower) regex to check if the string (coerced from numeric form) starts with the digit «1».

See
docs.raku.org/routine/starts-with for more information about `starts-with`

.

We get the same result:

$ ./permuted-multiples-fixed
142857
$ ./permuted-multiples-fixed 3
142857, 1428570, 1429857

Note that asking for e.g. 10 values will take a very long time, and nothing will be printed before all ten values have been computed. This is an inherent property of sequences. (Or at least, this type of sequence.)

$ ./permuted-multiples-fixed 10
142857, 1428570, 1429857, 14285700, 14298570, 14299857, 142857000, 142985700, 142998570, 142999857

We can work around it, e.g. like this:

File: permuted-multiples-unbuffered#! /usr/bin/env raku
unit sub MAIN (Int $count where $count > 0 = 1);
my $ptm := (^Inf).grep({ $_.starts-with('1') && $_.&is-pm });
for ^$count -> $index
{
my $val = $ptm[$index];
print ", " if $index; # [1]
print $val;
}
say ""; # [1a]
sub is-pm ($number)
{
my $n = $number.comb.sort.join;
my $n2 = ($number * 2).comb.sort.join;
my $n3 = ($number * 3).comb.sort.join;
my $n4 = ($number * 4).comb.sort.join;
my $n5 = ($number * 5).comb.sort.join;
my $n6 = ($number * 6).comb.sort.join;
return $n eq $n2 eq $n3 eq $n3 eq $n4 eq $n5 eq $n6;
}

[1]
Note the use of `print`

to get the values without a
trailing newline. Also note the `say`

after the loop to get the final
newline.

See
docs.raku.org/routine/print for more information about `print`

.

See
docs.raku.org/routine/say for more information about `say`

.

The output is the same, but it will print the values as soon as they are computed.

Write a script to find out all

A number is said to be a reversible if sum of the number and its reverse had only odd digits.

For example

File: reversible-numbers
`Reversible Numbers`

below `100`

.
A number is said to be a reversible if sum of the number and its reverse had only odd digits.

For example

36 is reversible number as 36 + 63 = 99 i.e. all digits are odd.
17 is not reversible as 17 + 71 = 88, none of the digits are odd.

Output
10, 12, 14, 16, 18, 21, 23, 25, 27,
30, 32, 34, 36, 41, 43, 45, 50, 52,
54, 61, 63, 70, 72, 81, 90

#! /usr/bin/env raku
unit sub MAIN (Int $limit where $limit > 0 = 100); # [1]
say (10 .. $limit).grep( *.&is-reversible ).join(", "); # [2]
sub is-reversible ($number) # [2a]
{
my $sum = $number + $number.flip; # [3]
return $sum !~~ /<[02468]>/; # [4]
}

[1] Note that this time we get the upper limit (of the values to consider), and not the number of values we want.

[2] We cannot have a reversible number with only one digit, as the that would give an even sum (the same as 2 times the number). So we start at 10.

[3]
Get the sum of the number and the number reversed, which we get with
`flip`

. (Note that `flip`

works on strings, as `reverse`

works on lists only).

See
docs.raku.org/routine/flip for more information about `flip`

.

See
docs.raku.org/routine/reverse for more information about `reverse`

.

[4]. We have a Reversible Number if the sum (from [3]) does **not** contain any even
digits (i.e. they are all odd).

Running it:

$ ./reversible-numbers
10, 12, 14, 16, 18, 21, 23, 25, 27, 30, 32, 34, 36, 41, 43, 45, 50, 52, 54,\
61, 63, 70, 72, 81, 90

Looking good.

And that's it.