perl logo Perl logo (Thanks to Olaf Alders)

The weekly challenge 398 - Task 2: String Difference

  1 #!/usr/bin/env perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-398/#TASK2
  3 #
  4 # Task 2: String Difference
  5 # =========================
  6 #
  7 # You are given an array of equal length strings.
  8 #
  9 # Write a script to find the difference integer array of each word in the given
 10 # array. There will be one word with a different array; return that word.
 11 #
 12 ###   Each words[i] can be converted into a difference integer array
 13 ###   difference[i] of length n - 1 where difference[i][j] = words[i][j+1] -
 14 ###   words[i][j]
 15 #
 16 ## Example 1
 17 ##
 18 ## Input: @words = ("ab", "bc", "cd", "zy")
 19 ## Output: "zy"
 20 ##
 21 ## "ab" => [1 - 0] = [1]
 22 ## "bc" => [2 - 1] = [1]
 23 ## "cd" => [3 - 2] = [1]
 24 ## "zy" => [24 - 25] = [-1]
 25 #
 26 ## Example 2
 27 ##
 28 ## Input: @words = ("cba", "fed", "azy")
 29 ## Output: "azy"
 30 ##
 31 ## "cba" => [1 - 2, 0 - 1] = [-1, -1]
 32 ## "fed" => [4 - 5, 3 - 4] = [-1, -1]
 33 ## "azy" => [25 - 0, 24 - 25] = [25, -1]
 34 #
 35 ## Example 3
 36 ##
 37 ## Input: @words = ("pop", "ada", "beb", "cfc")
 38 ## Output: "pop"
 39 ##
 40 ## "pop" => [14 - 15, 15 - 14] = [-1, 1]
 41 ## "ada" => [3 - 0, 0 - 3] = [3, -3]
 42 ## "beb" => [4 - 1, 1 - 4] = [3, -3]
 43 ## "cfc" => [5 - 2, 2 - 5] = [3, -3]
 44 #
 45 ## Example 4
 46 ##
 47 ## Input: @words = ("aaaa", "zzzz", "mmmm", "aaba")
 48 ## Output: "aaba"
 49 ##
 50 ## "aaaa" => [0 - 0, 0 - 0, 0 - 0] = [0, 0, 0]
 51 ## "zzzz" => [25 - 25, 25 - 25, 25 - 25] = [0, 0, 0]
 52 ## "mmmm" => [12 - 12, 12 - 12, 12 - 12] = [0, 0, 0]
 53 ## "aaba" => [0 - 0, 1 - 0, 0 - 1] = [0, 1, -1]
 54 #
 55 ## Example 5
 56 ##
 57 ## Input: @words = ("aceg", "bdfh", "cegi", "azbz")
 58 ## Output: "azbz"
 59 ##
 60 ## "aceg" => [2 - 0, 4 - 2, 6 - 4] = [2, 2, 2]
 61 ## "bdfh" => [3 - 1, 5 - 3, 7 - 5] = [2, 2, 2]
 62 ## "cegi" => [4 - 2, 6 - 4, 8 - 6] = [2, 2, 2]
 63 ## "azbz" => [25 - 0, 1 - 25, 25 - 1] = [25, -24, 24]
 64 #
 65 ############################################################
 66 ##
 67 ## discussion
 68 ##
 69 ############################################################
 70 #
 71 # First, we create all the difference integer arrays.
 72 # Then, we compare the first two of them. If they are equal,
 73 # we find the odd out out later in the array. If they are not
 74 # equal, we compare the second one with the third one. If those
 75 # are the same, then the first one is the odd one out, otherwise
 76 # the second one is the odd one out.
 77 
 78 use v5.36;
 79 
 80 sub string_difference(@words) {
 81     say "Input: (" . join(", ", map { "\"$_\""} @words) . ")";
 82     my $diff = {};
 83     foreach my $word (@words) {
 84         my @chars = split //, $word;
 85         my $values = [];
 86         foreach my $index (0..$#chars-1) {
 87             push @$values, (ord($chars[$index+1]) - ord($chars[$index]));
 88         }
 89         $diff->{$word} = $values;
 90     }
 91     if(array_equal($diff->{$words[0]}, $diff->{$words[1]})) {
 92         # find the odd one out later in @words
 93         foreach my $i (2..$#words) {
 94             return say "Output: $words[$i]"
 95                 unless array_equal($diff->{$words[0]}, $diff->{$words[$i]});
 96         }
 97     } else {
 98         # if $words[1] eq $words[2], then $words[0] is the odd one out,
 99         # otherwise $words[1] is the odd one out
100         if(array_equal($diff->{$words[1]}, $diff->{$words[2]})) {
101             return say "Output: $words[0]";
102         }
103         return say "Output: $words[1]";
104     }
105 }
106 
107 sub array_equal($arr1, $arr2) {
108     my @arr1 = @$arr1;
109     my @arr2 = @$arr2;
110     return 0 if scalar(@arr1) != scalar(@arr2);
111     foreach my $i (0..$#arr1) {
112         return 0 if $arr1[$i] != $arr2[$i];
113     }
114     return 1;
115 }
116 
117 
118 string_difference("ab", "bc", "cd", "zy");
119 string_difference("cba", "fed", "azy");
120 string_difference("pop", "ada", "beb", "cfc");
121 string_difference("aaaa", "zzzz", "mmmm", "aaba");
122 string_difference("aceg", "bdfh", "cegi", "azbz");