Peter’s blog ✴ Week 398 ✴ 2 November 2026

THE WEEKLY CHALLENGE
Divisible and difference

The Perl Camel

Task 2

String 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.

Examples


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]

Analysis

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.

Try it 

Your input:



eg: 'aceg', 'bdfh', 'cegi', 'azbz'

Script


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

Output from script


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