Logo

dev-resources.site

for different kinds of informations.

PWC 254, Task 2: I, Too, Wish to Make the "Vowel Movement" Joke

Published at
2/3/2024
Categories
perl
perlweeklychallenge
Author
boblied
Categories
2 categories in total
perl
open
perlweeklychallenge
open
Author
7 person written this
boblied
open
PWC 254, Task 2: I, Too, Wish to Make the "Vowel Movement" Joke

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.
Enter fullscreen mode Exit fullscreen mode
  • 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"

Ruminations

When the subject is vowels, I'm tempted to make the theme music "Old McDonald", but that is too inane even for me. Let's go with Red Hot Chili Peppers, Snow. The more I see, the less I know. Hey, oh.

Example 4 gives us an interesting implied requirement: the case of the result should match the case of the input.

My first thought is to do something like record the indexes of the vowels, and then do some math to map the indexes backward and indirectly access the letters of the string for swaps. My brain is already off-by-one just thinking about it.

Reversing a list is the classic computer science last-in-first-out stack. If we can get a list of the vowels in order, we can generate them in reverse order by popping off a stack. Getting that list is easily done with a regular expression match; in array context, it will directly give us the list:

sub revVow($s) {
    state $isVowel = qr/[aeiou]/i;

    my @v = $s =~ m/$isVowel/g;
Enter fullscreen mode Exit fullscreen mode

I'm saving the pattern for a vowel in a variable because I'm going to need it again. I'm using state because that makes it a static variable that only needs to get evaluated once. I need /g (global) at the end of the expression to get the list of all matches, and not just a count.

Leaving consonants untouched and moving the vowels is going to require something that iterates over the letters. We'll copy consonants from input to output, but each time we see a vowel, we'll pop the top element from the @v stack.

    my $rev;
    for ( split(//, $s) )
    {
        my $next = ( /$isVowel/ ? pop @v : $_ );
        $rev .= ( /\p{Uppercase}/ ? uc $next : lc $next );
    }
    return $rev;
Enter fullscreen mode Exit fullscreen mode

A few Perl points in this code:

  • Instead of making up a variable name for each character, I'm using the implicit topicalizer, $_. I generally prefer naming things, but in two lines of code without any nested blocks that have their own $_, it's easy enough to understand.
  • The implicit $_ is used in the pattern matching statements.
  • The regular expression $isVowel can be interpolated for pattern matching. It's static in this case, so I'm just using the variable to avoid repeating myself, but imagine that the definition could change (for different languages, say).
  • Perl has amazing Unicode support, including an extensive list of character classes and properties. I'm exploiting that to check for uppercase characters in /\p{Uppercase}/ in a very readable way.

Weekly Challenge problems generally keep things simple by restricting the strings to good old ASCII. I thought briefly about what it would take to extend the problem to a more general definition of vowels. I know nothing about non-European languages, but maybe we could handle accents and umlauts? In my brief search, I didn't find an easy way to specify a pattern match for something like "all forms of A with any kind of diacritical marks."

Looking over early answers, there was a clever solution that looked like this:

$str =~ s/[aeiou]/pop @v/ge;
Enter fullscreen mode Exit fullscreen mode

It's a straight substitution of vowels, except that the replacement comes from executing a bit of Perl code. That feature is enabled by adding /e to the substitution operator. I usually judge that as too magic, but in this case I think it's simple enough to be kind of elegant.

perlweeklychallenge Article's
30 articles in total
Favicon
Maximally Indexed Indices (PWC 298)
Favicon
PWC 296 String Compression
Favicon
PWC 293 Similar Dominos Done Badly
Favicon
Jump, but Don't Break the Game (PWC 295)
Favicon
Ups and Downs, Beginnings and Ends (PWC 297)
Favicon
Consecutive Sequences of Permutations, Anyone? (PWC 294)
Favicon
PWC 293 Similar Dominos Done Badly
Favicon
Domino Frequencies and the Vectorized Boomerang (PWC 293)
Favicon
PWC 287 Strength in Numbers
Favicon
PWC 281 Knight's Move
Favicon
PWC 274 Waiting at the Bus Stop
Favicon
PWC 269 Two of Us Distributing Elements
Favicon
PWC 267 Positively Perl Street
Favicon
PWC 268 Games Numbers Play
Favicon
PWC 263.1 Don't Sort It, Be Happy
Favicon
PWC 262 Grep it once, grep it twice
Favicon
PWC 258 How do I sum thee? Let me count the ones.
Favicon
PWC 259 Something I think's worthwhile if a parser makes you smile
Favicon
PWC 254, Task 2: I, Too, Wish to Make the "Vowel Movement" Joke
Favicon
PWC 254 Task 1, Three Power
Favicon
PWC 252 Special Numbers
Favicon
PWC 246 Random use of algebra
Favicon
Let me count the ways (PWC 244 Count Smaller)
Favicon
PWC 241 Triplets, sorting, and a profiling digression
Favicon
PWC 242 Flip the Script
Favicon
PWC 243 Sweeping the floor
Favicon
PWC 238 Running and Persistence
Favicon
PWC 239 Adagio for frayed knots
Favicon
PWC 235 Steppin' in a Slide Zone
Favicon
PWC 236 Task 1 A Change Would Do You Good

Featured ones: