1 #!/usr/bin/perl
  2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-208/#TASK1
  3 #
  4 # Task 1: Minimum Index Sum
  5 # =========================
  6 #
  7 # You are given two arrays of strings.
  8 #
  9 # Write a script to find out all common strings in the given two arrays with minimum index sum. If no common strings found returns an empty list.
 10 #
 11 ## Example 1
 12 ##
 13 ## Input: @list1 = ("Perl", "Raku", "Love")
 14 ##        @list2 = ("Raku", "Perl", "Hate")
 15 ##
 16 ## Output: ("Perl", "Raku")
 17 ##
 18 ## There are two common strings "Perl" and "Raku".
 19 ## Index sum of "Perl": 0 + 1 = 1
 20 ## Index sum of "Raku": 1 + 0 = 1
 21 #
 22 ## Example 2
 23 ##
 24 ## Input: @list1 = ("A", "B", "C")
 25 ##        @list2 = ("D", "E", "F")
 26 ##
 27 ## Output: ()
 28 ##
 29 ## No common string found, so no result.
 30 #
 31 ## Example 3
 32 ##
 33 ## Input: @list1 = ("A", "B", "C")
 34 ##        @list2 = ("C", "A", "B")
 35 ##
 36 ## Output: ("A")
 37 ##
 38 ## There are three common strings "A", "B" and "C".
 39 ## Index sum of "A": 0 + 1 = 1
 40 ## Index sum of "B": 1 + 2 = 3
 41 ## Index sum of "C": 2 + 0 = 2
 42 #
 43 ############################################################
 44 ##
 45 ## discussion
 46 ##
 47 ############################################################
 48 #
 49 # We have to find the index for every string in both arrays.
 50 # Then we find the index sum for each string.
 51 # Then we find the minimum value for the sums.
 52 # Then we output every string that has this minimum value as its sum.
 53 
 54 use strict;
 55 use warnings;
 56 use List::Util qw(min);
 57 
 58 index_sum( ["Perl", "Raku", "Love"], ["Raku", "Perl", "Hate"] );
 59 index_sum( ["A", "B", "C"], ["D", "E", "F"] );
 60 index_sum( ["A", "B", "C"], ["C", "A", "B"] );
 61 
 62 sub index_sum {
 63    my ($l1, $l2) = @_;
 64    my @list1 = @$l1;
 65    my @list2 = @$l2;
 66    my @result = ();
 67    my $index_data = {};
 68    print "Input: (" . join(", ", @list1) . "); (" . join(", ", @list2) . ")\n";
 69    # find the index for every string in list1
 70    foreach my $i (0..$#list1) {
 71       my $value = $list1[$i];
 72       $index_data->{$value}->{"list1_index"} = $i;
 73    }
 74    # find the index for every string in list2
 75    foreach my $j (0..$#list2) {
 76       my $value = $list2[$j];
 77       $index_data->{$value}->{"list2_index"} = $j;
 78    }
 79    # for each found string, if it exists in both lists, calculate the sum
 80    my @sums = ();
 81    foreach my $v (keys %$index_data) {
 82       if(defined($index_data->{$v}->{"list1_index"})
 83          && defined($index_data->{$v}->{"list2_index"})) {
 84          $index_data->{$v}->{"sum"} =
 85                 $index_data->{$v}->{"list1_index"}
 86                 + $index_data->{$v}->{"list2_index"};
 87          push @sums, $index_data->{$v}->{"sum"};
 88       }
 89    }
 90    # calculate the minimum sum
 91    my $minimum = min(@sums);
 92    # find all values that share the minimum index sum
 93    foreach my $v (keys %$index_data) {
 94       if(defined($index_data->{$v}->{"sum"})) {
 95          if($index_data->{$v}->{"sum"} == $minimum) {
 96             push @result, $v;
 97          }
 98       }
 99    }
100    # in order to avoid a random sort order of the results we sort by
101    # their index in list1
102    print "Output: (" . join(", ",
103       sort {
104          $index_data->{ $a }->{"list1_index"} <=>
105          $index_data->{ $b }->{"list1_index"} }
106       @result) . ")\n";
107 }