Peter’s blog ✴ Week 374 ✴ 18 May 2026
THE WEEKLY CHALLENGE
Lots of repetition
You are given a string. Write a script to return all possible vowel substrings in the given string. A vowel substring is a substring that only consists of vowels and has all five vowels present in it.
Example 1 Input: $str = 'aeiou' Output: ('aeiou') Example 2 Input: $str = 'aaeeeiioouu' Output: ('aaeeeiioou', 'aaeeeiioouu', 'aeeeiioou', 'aeeeiioouu') Example 3 Input: $str = 'aeiouuaxaeiou' Output: ('aeiou', 'aeiou', 'eiouua', 'aeiouu', 'aeiouua') Example 4 Input: $str = 'uaeiou' Output: ('aeiou', 'uaeio', 'uaeiou') Example 5 Input: $str = 'aeioaeioa' Output: ()
In terms of lines of code a simple way to solve this challenge
would be to use Algorithm::Combinatorics 'subsets' and check each
subset to see if it met the 'vowel substring' criterion.
But that would quickly get
very slow if the substring was long - say over 20 characters.
So I found a better, if a bit more complicated way.
First, let's get rid of some hopeless cases, such as a string missing any of the 5 vowels. That will also eliminate any string with fewer than 5 characters.
Now let's break the string into substrings at the places where non-vowels occur, so for example 'aeiouxuoiea' splits into substrings 'aeiou' and 'uoiea'.
For each substring I then test all the sub-substrings of 5 or more letters to see if they contain at least one of each vowel. If they do, they are an answer to the challenge, because we've already eliminated any non-vowels.
I tried this on a string of 10 000 characters comprising random vowels randomly interspersed with 10% of 'x', and the answer came back in about a second.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2026-05-18 use utf8; # Week 374 - task 1 - Count vowel use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; count_vowel('aeiou'); count_vowel('aaeeeiioouu'); count_vowel('aeiouuaxaeiou'); count_vowel('uaeiou'); count_vowel('aeioaeioa'); sub count_vowel { my ($string, @result, @subs, $sub, $sub_length, $s, $f, $subsub); # initialise $string = lc($_[0]); say qq[\nInput: '$string']; @result = (); # quick discards for ('a', 'e', 'i', 'o', 'u') { if ($string !~ m|$_|) { say qq[Output: ()]; return; } } # segment string at non-vowels push @subs, $1 while $string =~ m|([aeiou]+)|g; SUB: for $sub (@subs) { # eliminate substring if too short or missing a vowel $sub_length = length($sub); next SUB if $sub_length < 5; # look for string of vowels for $s (0 .. $sub_length - 5) { SUBSUB: for $f (4 .. $sub_length - 1) { $subsub = substr($sub, $s, $f - $s + 1); for ('a', 'e', 'i', 'o', 'u') { next SUBSUB if $subsub !~ m|$_|; } push @result, $subsub; } } } say qq[Output: ('] . join(q[', '], @result) . q[')]; }
20 lines of code
Completed after the closing date and not submitted to GitHub
Input: 'aeiou' Output: ('aeiou') Input: 'aaeeeiioouu' Output: ('aaeeeiioou', 'aaeeeiioouu', 'aeeeiioou', 'aeeeiioouu') Input: 'aeiouuaxaeiou' Output: ('aeiou', 'aeiouu', 'aeiouua', 'eiouua', 'aeiou') Input: 'uaeiou' Output: ('uaeio', 'uaeiou', 'aeiou') Input: 'aeioaeioa' Output: ()
Any content of this website which has been created by Peter Campbell Smith is in the public domain