by Arne Sommer

# Reverse Power with Raku

[274] Published 30. January 2024.

This is my response to The Weekly Challenge #254.

## Challenge #254.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 ```
File: three-power ```#! /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 ```

## Challenge #254.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" ```
File: reverse-vowels ```#! /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)