This week’s musical theme: Power of Two by the Indigo Girls. Listen to the song one-and-a-half times and you’ll have the power of three, right?
Onward to Perl Weekly Challenge 254!
Task 1: Three Power
You are given a positive integer, $n
.
Write a script to return true if the given integer is a power of three otherwise return false.
Example 1
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
Approach
Was it really three weeks ago that I last used recursion? Huh. Anyway, I’m going to have a function that takes two parameters, $n
and a number to raise to the power of three, $pow
. Initially, I call it with $pow = 0
. If $n == $pow ^ 3
, we return true
. If $n < $pow ^ 3
, we return false
(because the number is larger than the last power of three, but smaller than this one). Otherwise, we return the value returned by calling the function again with $pow + 1
. Eventually, we’ll match one of the first two conditions and return either true
or false
.
Raku
By using a default value for the second parameter, I can call isAPowerOfThree($n)
to begin with, and let the recursive calls pass the numbers that get raised to the power of three.
sub isAPowerOfThree($n, $pow = 0) {
if ($n == $pow ** 3) {
return 'true';
}
elsif ($n < $pow ** 3) {
return 'false';
}
return isAPowerOfThree($n, $pow + 1);
}
View the entire Raku script for this task on GitHub.
Perl
Since Perl’s function signatures (the default since Perl 5.36) allow for default values the same way Raku does, we don’t have to change anything except the string concatenation operator in my solution()
function (shown in the full solution). But if I wanted to be compatible back to Perl 5.10, I could write it this way.
sub isAPowerOfThree {
my $n = shift;
my $pow = shift() // 0;
if ($n == $pow ** 3) {
return 'true';
}
elsif ($n < $pow ** 3) {
return 'false';
}
return isAPowerOfThree($n, $pow + 1);
}
View the entire Perl script for this task on GitHub.
Python
For Python, I didn’t have to adjust the logic at all, only the syntax.
def isAPowerOfThree(n, pow = 0):
if n == pow ** 3:
return 'true'
elif n < pow ** 3:
return 'false'
return isAPowerOfThree(n, pow + 1)
Task 2: Reverse Vowels
You are given a string, $s
.
Write a script to reverse all the vowels (a, e, i, o, u
) in the given string.
Example 1
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"
Approach
Ah, this one requires a bit more thought. We want to extract the vowels from the string into a list, but maintain the positions of the vowels in the string. We then reverse the list and put the vowels back into the string. One thing to note: the output string is title-cased.
Raku
I realized that I didn’t need to remove the vowels from the string, so I could use the vowels themselves as the placeholders.
sub reverseVowels($s) {
# split string into letters
my @letters = $s.split('', :skip-empty);
# find the vowels
my @vowels = @letters.grep({ /:i<[aeiou]>/ });
# replace each vowel in reverse order, converting
# any uppercase letters to lowercase
for 0 .. @letters.end -> $i {
if (@letters[$i] ~~ /:i<[aeiou]>/) {
@letters[$i] = @vowels.pop.lc;
}
}
# rejoin the array as a string, title casing it
return tc(@letters.join(''));
}
View the entire Raku script for this task on GitHub.
Perl
sub reverseVowels($s) {
# split string into letters
my @letters = split(//, $s);
# find the vowels
my @vowels = grep { /[aeiou]/i } @letters;
# replace each vowel in reverse order, converting
# any uppercase letters to lowercase
foreach my $i ( 0 .. $#letters) {
if ($letters[$i] =~ /[aeiou]/i) {
$letters[$i] = lc(pop @vowels);
}
}
# rejoin the array as a string, title casing it
return ucfirst(join('', @letters));
}
View the entire Perl script for this task on GitHub.
Python
import re
is_vowel = re.compile('[aeiou]', re.IGNORECASE)
def reverseVowels(s):
# split string into letters
letters = list(s)
# find the vowels
vowels = [ v for v in letters if is_vowel.match(v) ]
# replace each vowel in reverse order, converting
# any uppercase letters to lowercase
for i in range(len(s)):
if is_vowel.match(letters[i]):
letters[i] = vowels.pop(-1)
# rejoin the array as a string, title casing it
return ''.join(letters).title()
Here’s all my solutions in GItHub: https://github.com/packy/perlweeklychallenge-club/tree/master/challenge-254/packy-anderson