Camel
Peter
Peter Campbell Smith

Base 2 dates and odd words

Weekly challenge 332 — 28 July 2025

Week 332: 28 Jul 2025

Task 2

Task — Odd letters

You are given a string. Write a script to find out if each letter in the given string appears an odd number of times.

Examples


Example 1
Input: $str = 'weekly'
Output: false
w: 1 time
e: 2 times
k: 1 time
l: 1 time
y: 1 time
The letter 'e' appeared 2 times i.e. even.

Example 2
Input: $str = 'perl'
Output: true

Example 3
Input: $source = 'challenge'
Output: false

Analysis

The first question that came to mind was: 'do we sort the string?'. If we did sort it, then we could then pass along and exit as soon as we found an even-frequency letter, so for example if the sorted string were 'aabbbccc ...' we could quit as soon as we saw the first 'b' because we know then that there is an even number of 'a'.

But sorting is quite expensive. We can meet this challenge with a single pass along the string, accumulating counts of each letter. We do need to check right to the end to cater for strings like 'abababababa'.

I used a hash to hold the counts, which will only need as many elements as there are different letters in the string. A 26-member array might be faster if the string is very long: a good example of not designing a solution without a comprehensive set of use cases!

For the record, I assumed that upper and lower cases of a letter were counted as the same, and, as the challenge didn't say otherwise, that non-letters might be present. So 'a44b' returns true, because all the letters - 'a' and 'b' - occur just once.

There remains the edge case of an empty string, or one contaning only non-letters, eg '12 + 13 = 25'. I judged that to be 'true', but you could argue for 'false' or even invalid data. Ask the client!

Try it 

Try running the script with any input:



example: Mississippi

Script


#!/usr/bin/perl

# Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

use v5.26;    # The Weekly Challenge - 2025-07-28
use utf8;     # Week 332 - task 2 - Odd letters
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

odd_letters('weekly');
odd_letters('You are given a string');
odd_letters('a bBb ccCcc dddDddd eeeeEeeee');
odd_letters('supercalifragilisticexpialidocious');
odd_letters('12345 +=-*<>');

sub odd_letters {
    
    my (%counts, $j);
    
    # initialise
    say qq[\nInput:  \$str = '$_[0]'];
    
    # count occurrences of each unique letter
    $counts{$_} ++ for split('', lc($_[0]));
    
    # see if the counts of letters are all odd
    for $j (keys %counts) {
        next if ($counts{$j} & 1 or $j !~ m|[a-z]|);
        say qq[Output: false ('$j' occurs $counts{$j} times)];
        return;
    }
    
    say qq[Output: true];
}

Output


Input:  $str = 'weekly'
Output: false ('e' occurs 2 times)

Input:  $str = 'You are given a string'
Output: false ('e' occurs 2 times)

Input:  $str = 'a bBb ccCcc dddDddd eeeeEeeee'
Output: true

Input:  $str = 'supercalifragilisticexpialidocious'
Output: false ('p' occurs 2 times)

Input:  $str = '12345 +=-*<>'
Output: true

 

Any content of this website which has been created by Peter Campbell Smith is in the public domain