Perl Weekly Challenge 254.
My solutions (task 1 and task 2 ) to the The Weekly Challenge - 254.
Task 1: Three Power
Submitted by: Mohammad S Anwar
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
(I interpret power of three as $n**3, not as 3**$n; otherwise I guess example 2 would be wrong.) An interesting solution would be to find the factors of the number and then check that their multiplicity is a multiple of three. But a quick and dirty solution is to simply take the cubic root, round it to an integer and check its third power equals the original number. This yields a simple oneliner.
Examples:
perl -MPOSIX=lround -E 'for(@ARGV){say "$_ -> ", $_==lround($_**(1/3))**3?"True":"False"}' 27 0 6
Results:
27 -> True
0 -> True
6 -> False
Curiously, the code above fails for negative numbers:
perl -MPOSIX=lround -E 'for(@ARGV){say "$_ -> ", $_==lround($_**(1/3))**3?"True":"False"}' -- -27
Results:
-27 -> False
The reason is that fractional powers of negative numbers are tricky. The solution is trivial, as (-1)**3=(-1); I simply take the absolute value.
perl -MPOSIX=lround -E 'for(@ARGV){say "$_ -> ", abs($_)==lround(abs($_)**(1/3))**3?"True":"False"}
' -- -27
Results:
-27 -> True
The full code is:
1 # Perl weekly challenge 254
2 # Task 1: Three Power
3 #
4 # See https://wlmb.github.io/2024/01/29/PWC254/#task-1-three-power
5 use v5.36;
6 use POSIX qw(lround);
7 die <<~"FIN" unless @ARGV;
8 Usage: $0 N1 [N2...]
9 to check if the integers N1 N2... are cubes
10 FIN
11 for(@ARGV){
12 warn("$_ not integer"),next unless $_ == lround($_);
13 say "$_ -> ", abs($_)==lround(abs($_)**(1/3))**3?"True":"False";
14 }
Examples:
./ch-1.pl 27 0 6 -27
Results:
27 -> True
0 -> True
6 -> False
-27 -> True
Task 2: Reverse Vowels
Submitted by: Mohammad S Anwar
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"
I can split the string into an array, make an array of the indices of
its vowels and use it to assign the reversed vowels to the positions
occupied by the original vowels. To be consistent with the examples, I
lc
the input and ucfirst
the output. This yields a one and a half liner,
assuming ASCII input.
Examples:
perl -E '
for(@ARGV){@x=split "", lc $_; @i=grep {$x[$_]=~/[aeiou]/}(0..@x-1); @x[@i]=reverse @x[@i];
say "$_ -> ", ucfirst join "", @x;}
' Raku Perl Julia Uiua
Results:
Raku -> Ruka
Perl -> Perl
Julia -> Jaliu
Uiua -> Auiu
The full code follows:
1 # Perl weekly challenge 254
2 # Task 2: Reverse Vowels
3 #
4 # See https://wlmb.github.io/2024/01/29/PWC254/#task-2-reverse-vowels
5 use v5.36;
6 die <<~"FIN" unless @ARGV;
7 Usage: $0 W1 [W2..]
8 to reverse the vowels in the words W1 W2...
9 FIN
10 for(@ARGV){
11 my @all = split "", lc $_;
12 my @vowel_indices=grep {$all[$_]=~/[aeiou]/} 0..@all-1;
13 @all[@vowel_indices]=reverse @all[@vowel_indices];
14 my $out=ucfirst join "", @all;
15 say "$_ -> $out";
16 }
Example:
./ch-2.pl Raku Perl Julia Jaiu Uiua
Results:
Raku -> Ruka
Perl -> Perl
Julia -> Jaliu
Jaiu -> Juia
Uiua -> Auiu
/;