This is my response to The Weekly Challenge #254.
$n
.
Input: $n = 27
Output: true
27 = 3 ^ 3
Example 2:
Input: $n = 0
Output: true
0 = 0 ^ 3
Example 3:
Input: $n = 6
Output: false
#! /usr/bin/env raku
unit sub MAIN ($n is copy where $n ~~ UInt, :v($verbose)); # [1]
while $n > 3 # [2]
{
print ": $n / 3 -> " if $verbose;
$n /= 3; # [3]
say $n if $verbose;
last if $n != $n.Int; # [4]
}
say $n == 0|3 ?? 'true' !! 'false'; # [5]
[1] Note the is copy
so that we can change the value later on (in [3]).
Also note that we check the value against the Unsigned Int type UInt
instead of enforcing the type on the variable, as the value in $n
can become a non-integer (in [3]).
[2] As long as we have more 3
s to extract (by factoring them out).
[3] Divide the value by three, and assign the value back. This may result in a non-integer.
[4] This check will bail out of the loop if we got a non-integer value. This will spare us for a lot of loop iterations in the worst case, at the cost of adding code (and time). Feel free to comment it out.
[5] Are we left with 3 (or the special case of 0, for the input value 0), if so we have succeeded and print «true». If not, print «false».
Running it:
$ ./three-power 27
true
$ ./three-power 0
true
$ ./three-power 6
false
Looking good.
With verbose mode:
$ ./three-power -v 27
: 27 / 3 -> 9
: 9 / 3 -> 3
true
$ ./three-power -v 0
true
$ ./three-power -v 6
: 6 / 3 -> 2
false
Let us try an arbitrary largish number. First with the check in [4] intact, and then without it:
$ ./three-power -v 999
: 999 / 3 -> 333
: 333 / 3 -> 111
: 111 / 3 -> 37
: 37 / 3 -> 12.333333
false
$ ./three-power -v 999
: 999 / 3 -> 333
: 333 / 3 -> 111
: 111 / 3 -> 37
: 37 / 3 -> 12.333333
: 12.333333 / 3 -> 4.111111
: 4.111111 / 3 -> 1.37037
false
Why restrict ourselves with the power of 3?
File: multi-power
#! /usr/bin/env raku
unit sub MAIN ($n is copy where $n ~~ UInt,
UInt :p(:$power) where $power > 0 = 3,
:v(:$verbose));
while $n > $power
{
print ": $n / $power -> " if $verbose;
$n /= $power;
say $n if $verbose;
last if $n != $n.Int;
}
say $n == 0|$power ?? 'true' !! 'false';
Specify the power as e.g. -p=2
or -power=2
, if the default 3 does not
suit you.
$ ./multi-power -power=2 512
true
$ ./multi-power -power=2 -v 512
: 512 / 2 -> 256
: 256 / 2 -> 128
: 128 / 2 -> 64
: 64 / 2 -> 32
: 32 / 2 -> 16
: 16 / 2 -> 8
: 8 / 2 -> 4
: 4 / 2 -> 2
true
$s
.
(a, e, i, o, u)
in the
given string.
Input: $s = "Raku"
Output: "Ruka"
Example 2:
Input: $s = "Perl"
Output: "Perl"
Example 3:
Input: $s = "Julia"
Output: "Jaliu"
Example 4:
Input: $s = "Uiua"
Output: "Auiu"
#! /usr/bin/env raku
unit sub MAIN ($s, :v(:$verbose)); # [1]
my @letters = $s.comb; # [2]
my @vowels = @letters.grep: * ~~ /<[aeiouAEIOU]>/; # [3]
my @reverse = @vowels.reverse; # [4]
if $verbose
{
say ":Letters: { @letters.join(",") }";
say ":Vowels: { @vowels.join(",") }";
say ":Reverse: { @reverse.join(",") }";
}
my @output = @letters.map({ m:i/<[aeiou]>/ ?? @reverse.shift !! $_ }); # [5]
say @output.join; # [6]
[1] A string of arbitrary size (and content).
[2] Get the individual letters.
[3] Get the vowels. Note the «ignore case» :i
modifier, instead of an explicit
list of uppercase vowels in the regex.
[4] Reverse the list of vowels.
[5] Map each letter in the input (the list) to either itself (non-vowel) or the first remaing (unused) reversed list of vowels.
[6] Print the result as a single string.
Running it:
$ ./reverse-vowels Raku
Ruka
$ ./reverse-vowels Perl
Perl
$ ./reverse-vowels Julia
Jaliu
$ ./reverse-vowels Uiua
auiU
The last one is not as specified in the challenge, but let us have a go at verbose mode before looking into that.
$ ./reverse-vowels -v Raku
:Letters: R,a,k,u
:Vowels: a,u
:Reverse: u,a
Ruka
$ ./reverse-vowels -v Perl
:Letters: P,e,r,l
:Vowels: e
:Reverse: e
Perl
$ ./reverse-vowels -v Julia
:Letters: J,u,l,i,a
:Vowels: u,i,a
:Reverse: a,i,u
Jaliu
$ ./reverse-vowels -v Uiua
:Letters: U,i,u,a
:Vowels: U,i,u,a
:Reverse: a,u,i,U
auiU
Ok. Let us try a palindrome:
$ ./reverse-vowels "never odd or even"
never odd or even
$ ./reverse-vowels -v "never odd or even"
:Letters: n,e,v,e,r, ,o,d,d, ,o,r, ,e,v,e,n
:Vowels: e,e,o,o,e,e
:Reverse: e,e,o,o,e,e
never odd or even
$ ./reverse-vowels "NEVER ODD or even"
NeVeR oDD Or EvEn
$ ./reverse-vowels -v "NEVER ODD or even"
:Letters: N,E,V,E,R, ,O,D,D, ,o,r, ,e,v,e,n
:Vowels: E,E,O,o,e,e
:Reverse: e,e,o,O,E,E
NeVeR oDD Or EvEn
Then we can have a go at the case of the wrong case, so to speak...
File: reverse-vowels-case
#! /usr/bin/env raku
unit sub MAIN ($s, :v(:$verbose));
my @letters = $s.comb;
my @vowels = @letters.grep: * ~~ /<[aeiouAEIOU]>/;
my @reverse = @vowels.reverse;
if $verbose
{
say ":Letters: { @letters.join(",") }";
say ":Vowels: { @vowels.join(",") }";
say ":Reverse: { @reverse.join(",") }";
}
my @output = @letters.map({
if /<[aeiou]>/ { @reverse.shift.lc; } # [1]
elsif /<[AEIOU]>/ { @reverse.shift.uc; } # [2]
else { $_; }
});
say @output.join;
[1] If the original vowel is lowercase, apply lc
to force the
replacement vowel to lowercase as well.
See docs.raku.org/routine/lc for more information about lc
.
[2] If the original vowel is uppercase, apply uc
to force the
replacement vowel to uppercase as well.
See docs.raku.org/routine/uc for more information about uc
.
And magically nothing seems to happen...
$ ./reverse-vowels-case "NEVER ODD or even"
NEVER ODD or even
Verbose mode will tell you otherwise:
$ ./reverse-vowels-case -v "NEVER ODD or even"
:Letters: N,E,V,E,R, ,O,D,D, ,o,r, ,e,v,e,n
:Vowels: E,E,O,o,e,e
:Reverse: e,e,o,O,E,E
NEVER ODD or even
Another one:
$ ./reverse-vowels-case -v "THIS IS not a test"
:Letters: T,H,I,S, ,I,S, ,n,o,t, ,a, ,t,e,s,t
:Vowels: I,I,o,a,e
:Reverse: e,a,o,I,I
THES AS not i tist
Ind that's at. (Pun intended)