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

/;

Written on January 29, 2024