Peter’s blog ✴ Week 380 ✴ 29 June 2026

THE WEEKLY CHALLENGE
Frequencies and degrees

The Perl Camel

Task 1

Sum of frequencies

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.

Examples


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

Analysis

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.

Try it 

Your input:



eg: supercalifragilisticexpialidocious

Script


#!/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

Output from script


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