Peter’s blog ✴ Week 380 ✴ 29 June 2026
THE WEEKLY CHALLENGE
Frequencies and degrees
You are given a string consisting of English letters. Write a script to find the vowel and consonant with maximum frequency. Return the sum of the two frequencies.
Example 1 Input: $str = 'banana' Output: 5 Vowel: 'a' appears 3 times. Consonant: 'n' appears 2 times, 'b' appears 1 time. Max frequency of vowel: 3 Max frequency of consonant: 2 Example 2 Input: $str = 'teestett' Output: 7 Vowel: 'e' appears 3 times. Consonant: 't' appears 4 times, 's' appears 1 time. Max frequency of vowel: 3 Max frequency of consonant: 4 Example 3 Input: $str = 'aeiouuaa' Output: 3 Vowel: 'a' appears 3 times, 'u' 2 times, 'e', 'i', 'o' 1 time each. Consonant: None. Max frequency of vowel: 3 Max frequency of consonant: 0 Example 4 Input: $str = 'rhythm' Output: 2 Vowel: None Consonant: 'h' appears 2 times, 'r', 'y', 't', 'm' 1 time each. Max frequency of vowel: 0 Max frequency of consonant: 2 Example 5 Input: $str = 'x' Output: 1 Vowel: None Consonant: 'x' appears 1 time. Max frequency of vowel: 0 Max frequency of consonant: 1
As usual, there are a number of ways of tackling this. Also as usual, I have tried to maximise efficiency and clarity, though in maximising efficiency I may have slightly complicated the code.
My algorithm starts by lower-casing the string and removing anything except [a-z]. The challenge does say 'English letters', which might include upper-case letters, but I decided to treat 'a' and 'A' as being the same letter.
I now make a single pass along the string, accumulating the
frequency of letter 'λ' in $freq[ord('λ')], so, for example
the number of 'a' in the string is $freq[97] because 'a' is represented
by Unicode decimal 97 = hex 61.
It's then just a case of checking the 5 vowel entries and 21
consonant entries in $freq[97 .. 122] to find the maxima,
and adding these together for the requested total.
There are two compromises here between efficiency and clarity.
The first is that I could have used a hash %freq for accumulating
the frequencies, so $freq{'a'} rather than $freq[ord('a')]
would be the frequency of 'a' in the string. The reason for choosing
the somewhat fussier-looking alternative is that accessing an array
element is much faster than a hash value. The other optimisation
is that I could
have used $freq[0 .. 25] rather than $freq[97 .. 122],
accessed using $freq[ord(λ) - ord('a')], but that looks
messier and involves an extra subtraction for each letter in
$string.
Now these efficiency measures will have a negligible impact on strings of a few 10s or 100s of characters. In real life I would ask the client how long his strings were likely to be, and how many of them needed to be handled every day - and multiply both of his estimates by at least 10 before deciding on ultimate efficiency.
But to check the speed of my algorithm I gave it a string of 10_000_000 random letters and it came up with the answer:
Output: 771589 : vowel 'o' = 385331, consonant 'f' = 386258
in 7 seconds, which I think would be good enough for most real purposes.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2026-06-29 use utf8; # Week 380 - task 1 - Sum of frequencies use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; sum_of_frequencies('abcde'); sum_of_frequencies(''); sum_of_frequencies('banana'); sum_of_frequencies('rhythm'); sum_of_frequencies('aeiouuu'); sum_of_frequencies( 'Writeascripttofindthevowelandconsonantwithmaximumfrequency' . 'Returnthesumoftwofrequencies'); sub sum_of_frequencies { my ($string, $j, $k, @freq, $max_v, $max_c); # initialise $string = shift; say qq[\nInput: '$string']; $string = lc($string); $string =~ s|[^a-z]||g; $freq[$_] = 0 for (ord('a') .. ord('z') + 4); $max_v = $max_c = '~'; # count frequencies of each letter in $string for $j (0 .. length($string) - 1) { $freq[ord(substr($string, $j, 1))] ++; } # find maximum frequencies for $k ('a', 'e', 'i', 'o', 'u') { $max_v = $k if $freq[ord($k)] > $freq[ord($max_v)]; } for $k ('b' .. 'd', 'f' .. 'h', 'j' .. 'n', 'p' .. 't', 'v' .. 'z') { $max_c = $k if $freq[ord($k)] > $freq[ord($max_c)]; } # report say qq[Output: ] . ($freq[ord($max_v)] + $freq[ord($max_c)]) . qq[ : vowel '$max_v' = $freq[ord($max_v)], ] . qq[consonant '$max_c' = $freq[ord($max_c)]]; }
18 lines of code
Input: 'abcde' Output: 2 : vowel 'a' = 1, consonant 'b' = 1 Input: '' Output: 0 : vowel '~' = 0, consonant '~' = 0 Input: 'banana' Output: 5 : vowel 'a' = 3, consonant 'n' = 2 Input: 'rhythm' Output: 2 : vowel '~' = 0, consonant 'h' = 2 Input: 'aeiouuu' Output: 3 : vowel 'u' = 3, consonant '~' = 0 Input: 'WriteascripttofindthevowelandconsonantwithmaximumfrequencyReturnth esumoftwofrequencies' Output: 19 : vowel 'e' = 10, consonant 't' = 9
Any content of this website which has been created by Peter Campbell Smith is in the public domain