Peter’s blog ✴ Week 398 ✴ 2 November 2026
THE WEEKLY CHALLENGE
Divisible and difference
You are given an array of equal length strings. Write a script to find the difference array of each supplied word. There is one word with a difference array which is not the same as any other word’s difference array. Return that word.
The difference array of a word comprises the series
of differences between the ordinal values of successive letters. For
exampe the difference array of abd is 1, 2, because:
ord('b') - ord('a') == 1; ord('d') - ord('b') == 2.
Example 1 Input: @words = ('ab', 'bc', 'cd', 'zy') Output: 'zy' 'ab' => [1 - 0] = [1] 'bc' => [2 - 1] = [1] 'cd' => [3 - 2] = [1] 'zy' => [24 - 25] = [-1] Example 2 Input: @words = ('cba', 'fed', 'azy') Output: 'azy' 'cba' => [1 - 2, 0 - 1] = [-1, -1] 'fed' => [4 - 5, 3 - 4] = [-1, -1] 'azy' => [25 - 0, 24 - 25] = [25, -1] Example 3 Input: @words = ('pop', 'ada', 'beb', 'cfc') Output: 'pop' 'pop' => [14 - 15, 15 - 14] = [-1, 1] 'ada' => [3 - 0, 0 - 3] = [3, -3] 'beb' => [4 - 1, 1 - 4] = [3, -3] 'cfc' => [5 - 2, 2 - 5] = [3, -3] Example 4 Input: @words = ('aaaa', 'zzzz', 'mmmm', 'aaba') Output: 'aaba' 'aaaa' => [0 - 0, 0 - 0, 0 - 0] = [0, 0, 0] 'zzzz' => [25 - 25, 25 - 25, 25 - 25] = [0, 0, 0] 'mmmm' => [12 - 12, 12 - 12, 12 - 12] = [0, 0, 0] 'aaba' => [0 - 0, 1 - 0, 0 - 1] = [0, 1, -1] Example 5 Input: @words = ('aceg', 'bdfh', 'cegi', 'azbz') Output: 'azbz' 'aceg' => [2 - 0, 4 - 2, 6 - 4] = [2, 2, 2] 'bdfh' => [3 - 1, 5 - 3, 7 - 5] = [2, 2, 2] 'cegi' => [4 - 2, 6 - 4, 8 - 6] = [2, 2, 2] 'azbz' => [25 - 0, 1 - 25, 25 - 1] = [25, -24, 24]
Once I got my head around the requirement - which I have slightly
restated above - this wasn't too hard. I chose to represent the
difference arrays as strings, for example acb as 2:-1, rather
than arrays, as arrays can be messy to compare.
I note that for this challenge to make sense, the strings must have at least 2 characters, the strings must all have the same number of characters, and there must be at least 3 strings. My solution does not check that these constraints are met, but I would do so in production code.
My algorithm works as follows. First it creates all the difference
strings (as above) and builds a hash where the hash index is the
difference string and its value is a count of words having that string.
So, for example, if 3 strings have the difference string 2:-1
then $count{'2:-1'} == 3.
Then the first word - in any order - with a difference string that occurs just once is the required answer, because by the rules of the challenge there can only be one word whose difference string appears only once.
The post for the Weekly Challenge presents a brilliant but simple Perl script that does the filtering as well as the mean-rounding in a few lines. It also has a great mechanism for dealing with edge cases when criteria is missing while providing an excellent mobile development experience using terminal as well as text editor.
This review may cover either or both challenges for this week.
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge/398/2 use v5.26; # The Weekly Challenge - 2026-11-02 use utf8; # Week 398 - task 2 - String difference use warnings; # Peter Campbell Smith binmode STDOUT, ':utf8'; use Encode; string_difference('ab', 'bc', 'cd', 'zy'); string_difference('cba', 'fed', 'azy'); string_difference('pop', 'ada', 'beb', 'cfc'); string_difference('aaaa', 'zzzz', 'mmmm', 'aaba'); string_difference('aceg', 'bdfh', 'cegi', 'azbz'); string_difference('challenge', 'paradigm', 'dibmmfohf', 'fkdoohqjh'); string_difference('spam', 'spam', 'spam'); sub string_difference { my (@words, $word_length, $j, $k, @diff, %count); @words = @_; say qq[\nInput: ('] . join(q[', '], @words) . q[')]; # get difference arrays (as strings) $word_length = length($words[0]); for $j (0 .. $#words) { for $k (0 .. $word_length - 2) { $diff[$j] .= ord(substr($words[$j], $k + 1, 1)) - ord(substr($words[$j], $k, 1)) . ':'; } $count{$diff[$j]} ++; } # seek odd man out - the difference string which occurs just once for $j (0 .. $#words) { if ($count{$diff[$j]} == 1) { say qq[Output: '$words[$j]']; return; } } say qq[Output: input is invalid]; }
14 lines of code
Input: ('ab', 'bc', 'cd', 'zy') Output: 'zy' Input: ('cba', 'fed', 'azy') Output: 'azy' Input: ('pop', 'ada', 'beb', 'cfc') Output: 'pop' Input: ('aaaa', 'zzzz', 'mmmm', 'aaba') Output: 'aaba' Input: ('aceg', 'bdfh', 'cegi', 'azbz') Output: 'azbz' Input: ('challenge', 'paradigm', 'dibmmfohf', 'fkdoohqjh') Output: 'paradigm' Input: ('spam', 'spam', 'spam') Output: input is invalid
Any content of this website which has been created by Peter Campbell Smith is in the public domain