Base 2 dates and odd words
Weekly challenge 332 — 28 July 2025
Week 332: 28 Jul 2025
You are given a string. Write a script to find out if each letter in the given string appears an odd number of times.
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
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!
#!/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]; }
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