This is my response to The Weekly Challenge #379.
Input: $str = ""
Output: ""
Example 2:
Input: $str = "reverse the given string"
Output: "gnirts nevig eht esrever"
Example 3:
Input: $str = "Perl is Awesome"
Output: "emosewA si lreP"
Example 4:
Input: $str = "v1.0.0-Beta!"
Output: "!ateB-0.0.1v"
Example 5:
Input: $str = "racecar"
Output: "racecar"
#! /usr/bin/env raku
multi sub MAIN ($str where $str.chars > 0)
{
say ($str.chars -1 ... 0).map({ $str.substr($_,1) }).join;
}
multi sub MAIN ($str where $str.chars == 0)
{
say "";
}
[3] This code block does not work if we give it an empty
string, so we wrap it in a multi sub MAIN that is only used if we get
a non-empty string.
See docs.raku.org/syntax/multi for more information about multi.
[5] Take all the indices in the string, from the end towards 0, apply
map on each index to get the (single) character at that index.
Then we join the characters and print the result.
[8] This version handles empty strings;
[10] in which case we print an empty string.
A more elegant solution, perhaps:
File: reverse-string-pop#! /usr/bin/env raku
unit sub MAIN ($str);
my @input = $str.comb;
print @input.pop while @input;
say "";
[3] No empty/not empty restrictions on the string this time around.
[5] Split the string into a list of individual characters
(with comb).
See docs.raku.org/routine/comb for more information about comb.
[7] As long as the list is non-empty (the while), get the last
character (with pop) and print it.
[9] Add a final newline.
Running it:
$ ./reverse-string-substr ""
$ ./reverse-string-pop ""
$ ./reverse-string-substr "reverse the given string"
gnirts nevig eht esrever
$ ./reverse-string-pop "reverse the given string"
gnirts nevig eht esrever
$ ./reverse-string-substr "Perl is Awesome"
emosewA si lreP
$ ./reverse-string-pop "Perl is Awesome"
emosewA si lreP
$ ./reverse-string-substr 'v1.0.0-Beta!'
!ateB-0.0.1v
$ ./reverse-string-pop 'v1.0.0-Beta!'
!ateB-0.0.1v
$ ./reverse-string-substr "racecar"
racecar
$ ./reverse-string-pop "racecar"
racecar
Looking good.
Verbose mode did not make much sense.
Input: $base = 10, $limit = 1000
Output: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407)
Example 2:
Input: $base = 7, $limit = 1000
Output: (0, 1, 2, 3, 4, 5, 6, 10, 25, 32, 45, 133, 134, 152, 250)
Example 3:
Input: $base = 16, $limit = 1000
Output: (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 342, \
371, 520, 584, 645)
#! /usr/bin/env raku
unit sub MAIN (UInt :$base where 36 >= $base >= 2,
UInt :$limit where $limit > 0 = 1000,
:l(:$loquacious),
:v(:$verbose) = $loquacious);
my @result;
for 1 .. $limit -1 -> $i
{
my $in-base = $i.base($base);
my $sum =
$in-base.comb.map({ $_ ** $in-base.chars }).sum;
my $is-armstrong = $i eq $sum;
say ": $i (base $base) -> $in-base -> $sum \
{ $is-armstrong ?? "yes" !! "no" }"
if $loquacious || ($verbose && $is-armstrong);
@result.push: $i if $is-armstrong;
}
say "(" ~ @result.join(", ") ~ ")";
[3] The base as an (unsigned) integer between 2 and 36, both included,
as that is the range of what base (in [12]) can handle.
[4] The limit, with a default value of 1000 - as used in the examples.
[5] Loquacious is an excessively verbose mode, and it enables the normal verbose mode as well (in [9]).
[8] The result will end up here.
[10] Iterate over the numbers from 0 to the (decimal) limit.
[12] Use base to convert the decimal number into the
given base.
See docs.raku.org/routine/base for more information about base.
[13,14] Raise each digit to the power of the number of digits in the original number, and add them up.
[16] Do we have an Armstrong number?
[22] If so, add it to the result.
[25] Pretty print the result.
Running it:
$ ./armstrong-number -base=10
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407)
$ ./armstrong-number -base=7
(0, 1, 2, 3, 4, 5, 6, 10, 25, 32, 45, 133, 134, 152, 250)
$ ./armstrong-number -base=16
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 342, 371, 520, 584, 645)
Looking good.
With verbose mode:
$ ./armstrong-number -base=10 -v
: 0 (base 10) -> 0 -> 0 yes
: 1 (base 10) -> 1 -> 1 yes
: 2 (base 10) -> 2 -> 2 yes
: 3 (base 10) -> 3 -> 3 yes
: 4 (base 10) -> 4 -> 4 yes
: 5 (base 10) -> 5 -> 5 yes
: 6 (base 10) -> 6 -> 6 yes
: 7 (base 10) -> 7 -> 7 yes
: 8 (base 10) -> 8 -> 8 yes
: 9 (base 10) -> 9 -> 9 yes
: 153 (base 10) -> 153 -> 153 yes
: 370 (base 10) -> 370 -> 370 yes
: 371 (base 10) -> 371 -> 371 yes
: 407 (base 10) -> 407 -> 407 yes
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 153, 370, 371, 407)
$ ./armstrong-number -base=7 -v
: 0 (base 7) -> 0 -> 0 yes
: 1 (base 7) -> 1 -> 1 yes
: 2 (base 7) -> 2 -> 2 yes
: 3 (base 7) -> 3 -> 3 yes
: 4 (base 7) -> 4 -> 4 yes
: 5 (base 7) -> 5 -> 5 yes
: 6 (base 7) -> 6 -> 6 yes
: 10 (base 7) -> 13 -> 10 yes
: 25 (base 7) -> 34 -> 25 yes
: 32 (base 7) -> 44 -> 32 yes
: 45 (base 7) -> 63 -> 45 yes
: 133 (base 7) -> 250 -> 133 yes
: 134 (base 7) -> 251 -> 134 yes
: 152 (base 7) -> 305 -> 152 yes
: 250 (base 7) -> 505 -> 250 yes
(0, 1, 2, 3, 4, 5, 6, 10, 25, 32, 45, 133, 134, 152, 250)
$ ./armstrong-number -base=16 -v
: 0 (base 16) -> 0 -> 0 yes
: 1 (base 16) -> 1 -> 1 yes
: 2 (base 16) -> 2 -> 2 yes
: 3 (base 16) -> 3 -> 3 yes
: 4 (base 16) -> 4 -> 4 yes
: 5 (base 16) -> 5 -> 5 yes
: 6 (base 16) -> 6 -> 6 yes
: 7 (base 16) -> 7 -> 7 yes
: 8 (base 16) -> 8 -> 8 yes
: 9 (base 16) -> 9 -> 9 yes
: 10 (base 16) -> A -> 10 yes
: 11 (base 16) -> B -> 11 yes
: 12 (base 16) -> C -> 12 yes
: 13 (base 16) -> D -> 13 yes
: 14 (base 16) -> E -> 14 yes
: 15 (base 16) -> F -> 15 yes
: 342 (base 16) -> 156 -> 342 yes
: 371 (base 16) -> 173 -> 371 yes
: 520 (base 16) -> 208 -> 520 yes
: 584 (base 16) -> 248 -> 584 yes
: 645 (base 16) -> 285 -> 645 yes
(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 342, 371, 520, 584, 645)
Feel free to have a go at loquacious mode...
And that's it.