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 be one word with a difference array which is not the same as any other words'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') is 1 and ord('d') - ord('b') is 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 are 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.
#!/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