Triumvirate and Treamviruti?
Weekly challenge 254 — 29 January 2024
Week 254: 29 Jan 2024
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"
If there is a one-liner for this then I'm afraid it has eluded me.
My solution starts by converting the input string into an array of individual letters.
I then set two pointers to the start and end of the array and move each inward until they are both pointing at a vowel, at which point I switch the two vowels.
I repeat that until the pointers meet, and then convert the array back into a string.
It would be possible to do this without converting the string to an array by using
the fact that substr()
can be an lvalue, so
for example you could use substr($s, $p1, 1) = substr($s, $p2, 1)
.
You could also skip the switching of each pair of vowels if they were in fact
the same vowel (eg in 'noon') but the savings for either of these will be only few
microseconds, if anything.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2024-01-29 use utf8; # Week 254 task 2 - Reverse vowels use strict; # Peter Campbell Smith use warnings; binmode STDOUT, ':utf8'; reverse_vowels('triumvirate'); reverse_vowels('bcdf'); reverse_vowels('bcdfa'); reverse_vowels('abcdf'); reverse_vowels('aeiou'); reverse_vowels('aeiiou'); reverse_vowels('supercalifragilisticexpialidocious'); sub reverse_vowels { my ($s, $p1, $p2, $x, @letters); # initialise $s = lc(shift); @letters = split('', $s); $p1 = 0; $p2 = scalar(@letters) - 1; # loop while left pointer left of right pointer LOOP: while ($p1 < $p2) { # if left pointer has found a vowel if ($letters[$p1] =~ m|[aeiou]|) { # wind back right pointer until it meets a vowel or left pointer while ($p1 < $p2) { # right pointer has found a vowel, so switch left and right if ($letters[$p2] =~ m|[aeiou]|) { $x = $letters[$p2]; $letters[$p2 --] = $letters[$p1]; $letters[$p1 ++] = $x; next LOOP; # not a vowel, move right pointer to the left } else { $p2 --; } } # not a vowel, so move left pointer to the right } else { $p1 ++; } } say qq[\nInput: \$s = '$s'\nOutput: '] . join('', @letters), qq[']; }
Input: $s = 'triumvirate' Output: 'treamviruti' Input: $s = 'bcdf' Output: 'bcdf' Input: $s = 'bcdfa' Output: 'bcdfa' Input: $s = 'abcdf' Output: 'abcdf' Input: $s = 'aeiou' Output: 'uoiea' Input: $s = 'aeiiou' Output: 'uoiiea' Input: $s = 'supercalifragilisticexpialidocious' Output: 'suporcilofrigalistecixpiiladicaeus'
Any content of this website which has been created by Peter Campbell Smith is in the public domain