Peter’s blog ✴ Week 314 ✴ 24 March 2025

THE WEEKLY CHALLENGE
Even more strings

The Perl Camel

Task 1

Equal strings

You are given three strings. You are allowed to remove the rightmost character of a string to make all equal. Write a script to return the number of operations to make it equal otherwise -1.

Examples


Example 1
Input: $s1 = "abc", $s2 = "abb", $s3 = "ab"
Output: 2
Operation 1: Delete "c" from the string "abc"
Operation 2: Delete "b" from the string "abb"

Example 2
Input: $s1 = "ayz", $s2 = "cyz", $s3 = "xyz"
Output: -1

Example 3
Input: $s1 = "yza", $s2 = "yzb", $s3 = "yzc"
Output: 3

Analysis

My approach to this is:

  • Count the total number of characters ($all) in all three strings
  • Count the number of characters ($n) that match in all 3 strings
  • The answer is $all - 3 * $n

There is an edge case where all 3 strings are identical and we return 0.

Perl Weekly’s review

from Perl Weekly issue 714

Smart move for catching the edge case. Well documented solution and bonus DIY tool as always. Super cool, keep it up.

Try it 

Try running the script with any input:



example: horse, house, hoarse

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-03-24
use utf8;     # Week 314 - task 1 - Equal strings
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

equal_strings('abc', 'abb', 'ab');
equal_strings('ayz', 'cyz', 'xyz');
equal_strings('yza', 'yzb', 'yzc');

equal_strings('', 'ijk', 'ijk');
equal_strings('mno', '', '');
equal_strings('abc', 'abc', 'abc');
equal_strings('ab', 'abc', 'abc');
equal_strings('abcd', 'abc', 'abc');

sub equal_strings {
    
    my (@strings, $all, $keep, $n, $test);
    
    # initialise
    @strings = @_;
    say qq[\nInput:  \@strings = ('] . join(qq[', '], @strings) . qq[')];
    
    # get total characters in all strings
    $all += length($_) for @strings;
    
    # check match of first 1, 2 ... chars
    for $n (1 .. 99) {
        $test = substr($strings[0], 0, $n);
        
        # if they all match keep going
        if (substr($strings[1], 0, $n) eq $test and substr($strings[2], 0, $n) eq $test) {
            $keep += 3;
        
        # else we're done
        } else {
            say qq[Output: ] . ($keep ? $all - $keep : -1);
            return;
        }
    }
    
    # but there is an edge case where all 3 match
    say qq[Output: 0];
    return;
}

14 lines of code

Output from script


Input:  @strings = ('abc', 'abb', 'ab')
Output: 2

Input:  @strings = ('ayz', 'cyz', 'xyz')
Output: -1

Input:  @strings = ('yza', 'yzb', 'yzc')
Output: 3

Input:  @strings = ('', 'ijk', 'ijk')
Output: -1

Input:  @strings = ('mno', '', '')
Output: -1

Input:  @strings = ('abc', 'abc', 'abc')
Output: 0

Input:  @strings = ('ab', 'abc', 'abc')
Output: 2

Input:  @strings = ('abcd', 'abc', 'abc')
Output: 1

 

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