Power to the vowels
Tags: perl, python, theweeklychallenge
Published: 2024-02-03 05:50:23

## Weekly Challenge 254

Each week Mohammad S. Anwar sends out [The Weekly Challenge](https://theweeklychallenge.org/), a chance for all of us to come up with solutions to two weekly tasks. My solutions are written in Python first, and then converted to Perl. It's a great way for us all to practice some coding.

[Challenge](https://theweeklychallenge.org/blog/perl-weekly-challenge-254/), [My solutions](https://github.com/manwar/perlweeklychallenge-club/tree/master/challenge-254/sgreen)

## Task 1: Three Power

### Task

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.

### My solution

There are two things to consider when doing this task.

* Floating point math is not always going to give you the result you want. Julia Evans makes an excellent [blog post](https://jvns.ca/blog/2023/02/08/why-does-0-1-plus-0-2-equal-0-30000000000000004/) about why 0.1 + 0.2 is not 0.3.
* Python sometimes treats the cube root of a negative number as a complex number. I can't seem to find a better reference than this [Stack Exchange](https://math.stackexchange.com/questions/25528/cubic-root-of-negative-numbers) post.

With that in mind, we know we can get the approximate cube root by applying the function n <sup>(1÷3)</sup>, written as `n ** (1/3)` in code. I do this, round the number to the nearest integer, and then check if that number cubed is the original number.

To get around the negative number issue, I take the absolute value.

```python
def three_power(n: int) -> bool:
    i = round(abs(n) ** (1/3))
    return i ** 3 == abs(n)
```

### Examples

```bash
$ ./ch-1.py 27
true

$ ./ch-1.py 0
true

$ ./ch-1.py 6
false

$ ./ch-1.py -8
true
```

## Task 2: Reverse Vowels

### Task

You are given a string, `$s`.

Write a script to reverse all the vowels (`a`, `e`, `i`, `o`, `u`) in the given string.

### My solution

This is one of those tasks where the Python and Perl versions are slightly different. This is because in Python strings are immutable (i.e. cannot be changed). This has the upside that strings are iterable.

The first thing I do is convert the string to lower case, and extract all the vowels into a list.

```python
def reverse_vowels(s: str) -> str:
    s = s.lower()
    vowel_list = [c for c in s if c in 'aeiou']
```

I then loop through each letter of the string. If the letter is a vowel, I pop the last value off the `vowel_list` list and add it to the `new_string` variable. If it isn't, I add the character as is.

```python
    new_string = ''
    for c in s:
        if c in 'aeiou':
            new_string += vowel_list.pop()
        else:
            new_string += c
```

Finally I return the string with the first letter capitalized.

```python
    return new_string.capitalize()
```

As I mentioned, the Perl code is slightly different. For this code, I loop through each position in the string. If the letter at that position is a vowel, then I replace it. `substr` can be used as a l-value in Perl

```perl
for my $pos ( 0 .. length($s) - 1 ) {
    if ( substr( $s, $pos, 1 ) =~ /[aeiou]/ ) {
        substr( $s, $pos, 1 ) = pop(@vowel_list);
    }
}
```

### Examples

```bash
$ ./ch-2.py Raku
Ruka

$ ./ch-2.py Perl
Perl

$ ./ch-2.py Julia
Jaliu

$ ./ch-2.py Uiua
Auiu
```