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.
Peter utilising natively fast ASCII byte operations and provides a very elegant and performance-based method to solving weekly challenge. With the help of integer array indices created through the ord() function instead of performing heavier hash lookups, Peter produces an outstandingly fast frequency counter.
#!/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