Camel
Peter
Peter Campbell Smith

Acronyms and FS

Weekly challenge 317 — 14 April 2025

Week 317: 14 Apr 2025

Task 2

Task — Friendly strings

You are given two strings. Write a script to return true if swapping any two letters in one string match the other string, or return false otherwise.

Examples


Example 1
Input: $str1 = 'desc', $str2 = 'dsec'
Output: true

Example 2
Input: $str1 = 'tuck', $str2 = 'tcuk'
Output: true

Example 3
Input: $str1 = 'poo', $str2 = 'eop'
Output: false

Example 4
Input: $str1 = 'stripe', $str2 = 'sprite'
Output: true

Analysis

This is slightly harder than it looks because there are some edge cases.

The first step is to return false if the strings are different lengths because they can never match the conditions.

For the next step I originally considered:

  • check the corresponding characters in each string to see if they differ
  • if there are precisely two such pairs, and they are, eg, a, b and b, a ...
  • then the answer is true, and if not, it is false

But consider a case such as identical and identical. The algorithm above will return false because there are no places where the corresponding characters in the two strings differ. However, we can swap the first i in the first string with the second i in that string, and while that leaves the string unchanged, it does now match the second string and thus meets the stated conditions of the challenge, so the result is true.

I could have retained my original algorithm, and then done an additional chack for a case like identical, but I concluded that the easiest and most foolproof solution was the simple one of swapping all the possible pairs in the first string and seeing if it matches the second one. Even for a very long word that will take negligible time.

Try it 

Try running the script with any input:



example: spot



example: stop

Script


#!/usr/bin/perl

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

use v5.26;    # The Weekly Challenge - 2025-04-14
use utf8;     # Week 317 - task 2 - Friendly strings
use warnings; # Peter Campbell Smith
binmode STDOUT, ':utf8';
use Encode;

# these are true
friendly_strings('stripe', 'sprite');
friendly_strings('xxAxxBxx', 'xxBxxAxx');
friendly_strings('AxxxxxxB', 'AxxxxxxB');
friendly_strings('mmmmm', 'mmmmm');
friendly_strings('hippopotamus', 'hippopotamsu');
friendly_strings('identical', 'identical');

# these are false
friendly_strings('shorter', 'shorterx');
friendly_strings('longer', 'longe');
friendly_strings('completely', 'differents');
friendly_strings('friendly', 'friendly');

sub friendly_strings {
    
    my ($string1, $string2, $result, @chars1, $j, $k, @chars3, $string3, $x);
    
    # initialise
    ($string1, $string2) = @_;
        $result = 'false';
    @chars1 = split('', $string1);
    
    # strings must be same length
    if (length($string1) == length($string2)) {
        
        # loop over all pairs
        F: for $j (0 .. length($string1) - 2) {
            for $k ($j + 1 .. length($string1) - 1) {
                
                # swap 2 characters in string1
                @chars3 = @chars1;
                $x = $chars3[$j];
                $chars3[$j] = $chars3[$k];
                $chars3[$k] = $x;
                $string3 = join('', @chars3);
                
                # and compare with string2
                if ($string3 eq $string2) {
                    $result = qq[true - '$x' and '$chars3[$j]'];
                    last F;
                }
            }
        }           
    }
    
    # report results
    say qq[\nInput:  \$string1 = '$string1', \$string2 = '$string2'];
    say qq[Output: $result];
}

Output


Input:  $string1 = 'stripe', $string2 = 'sprite'
Output: true - 't' and 'p'

Input:  $string1 = 'xxAxxBxx', $string2 = 'xxBxxAxx'
Output: true - 'A' and 'B'

Input:  $string1 = 'AxxxxxxB', $string2 = 'AxxxxxxB'
Output: true - 'x' and 'x'

Input:  $string1 = 'mmmmm', $string2 = 'mmmmm'
Output: true - 'm' and 'm'

Input:  $string1 = 'hippopotamus',
   $string2 = 'hippopotamsu'
Output: true - 'u' and 's'

Input:  $string1 = 'identical', $string2 = 'identical'
Output: true - 'i' and 'i'

Input:  $string1 = 'shorter', $string2 = 'shorterx'
Output: false

Input:  $string1 = 'longer', $string2 = 'longe'
Output: false

Input:  $string1 = 'completely', $string2 = 'differents'
Output: false

Input:  $string1 = 'friendly', $string2 = 'friendly'
Output: false

 

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