This is my response to The Weekly Challenge #176.
x
such that
x, 2x, 3x, 4x, 5x
and 6x
are permuted multiples of each other.
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.
Reversible Numbers
below 100
.
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.