The weekly challenge 317 - Task 2: Friendly Strings
1 #!/usr/bin/env perl 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-317/#TASK2 3 # 4 # Task 2: Friendly Strings 5 # ======================== 6 # 7 # You are given two strings. 8 # 9 # Write a script to return true if swapping any two letters in one string match 10 # the other string, return false otherwise. 11 # 12 ## Example 1 13 ## 14 ## Input: $str1 = "desc", $str2 = "dsec" 15 ## Output: true 16 # 17 # 18 ## Example 2 19 ## 20 ## Input: $str1 = "fuck", $str2 = "fcuk" 21 ## Output: true 22 # 23 # 24 ## Example 3 25 ## 26 ## Input: $str1 = "poo", $str2 = "eop" 27 ## Output: false 28 # 29 # 30 ## Example 4 31 ## 32 ## Input: $str1 = "stripe", $str2 = "sprite" 33 ## Output: true 34 # 35 ############################################################ 36 ## 37 ## discussion 38 ## 39 ############################################################ 40 # 41 # There is a pretty simple solution to this problem that just needs 42 # to take care of a few corner cases. 43 # 1. If the length of the two strings doesn't match, we can return false 44 # 2. We walk both strings simultaneously. If the two strings happen to 45 # be equal everywhere except for two places, and the characters in 46 # those two places are just exchanged, we can return true 47 # 3. The missing corner case: if the two strings are actually the same, 48 # but have at least one duplicate character, we can also return true. If 49 # they are the same without duplicate characters, we can't swap two 50 # characters to make the strings match, so we return false. 51 52 use v5.36; 53 54 friendly_strings("desc", "dsec"); 55 friendly_strings("fuck", "fcuk"); 56 friendly_strings("poo", "eop"); 57 friendly_strings("stripe", "sprite"); 58 friendly_strings("foo", "foo"); 59 friendly_strings("bar", "bar"); 60 61 sub friendly_strings($str1, $str2) { 62 say "Input: '$str1', '$str2'"; 63 return say "Output: false" if length($str1) != length($str2); 64 my @chars1 = split //, $str1; 65 my @chars2 = split //, $str2; 66 my $found_chars = {}; 67 my @diff = (); 68 foreach my $i (0..$#chars1) { 69 $found_chars->{$chars1[$i]}++; 70 if($chars1[$i] ne $chars2[$i]) { 71 push @diff, [$chars1[$i], $chars2[$i]]; 72 } 73 } 74 if(scalar(@diff) == 2) { 75 if($diff[0]->[0] eq $diff[1]->[1] && $diff[0]->[1] eq $diff[1]->[0]) { 76 say "Output: true"; 77 } else { 78 say "Output: false"; 79 } 80 } elsif (scalar(@diff) == 0) { 81 foreach my $char (keys %$found_chars) { 82 return say "Output: true" if $found_chars->{$char} > 1; 83 } 84 say "Output: false"; 85 } else { 86 say "Output: false"; 87 } 88 }