The weekly challenge 229 - Task 2: Two out of Three

 1 #!/usr/bin/perl
 2 # https://theweeklychallenge.org/blog/perl-weekly-challenge-229/#TASK2
 3 #
 4 # Task 2: Two out of Three
 5 # ========================
 6 #
 7 # You are given three array of integers.
 8 #
 9 # Write a script to return all the elements that are present in at least 2 out of 3 given arrays.
10 #
11 ## Example 1
12 ##
13 ## Input: @array1 = (1, 1, 2, 4)
14 ##        @array2 = (2, 4)
15 ##        @array3 = (4)
16 ## Ouput: (2, 4)
17 #
18 ## Example 2
19 ##
20 ## Input: @array1 = (4, 1)
21 ##        @array2 = (2, 4)
22 ##        @array3 = (1, 2)
23 ## Ouput: (1, 2, 4)
24 #
25 ############################################################
26 ##
27 ## discussion
28 ##
29 ############################################################
30 #
31 # First, we generate a list of unique elements per array.
32 # Second, we count how many times each element in those unique
33 # lists appear altogether. If that happens to be at least 2
34 # times we found an element for our result. Since sorting those
35 # elements can easily be done when enumerating them, let's
36 # just do that as well.
37 
38 use strict;
39 use warnings;
40 
41 two_out_of_three( [1, 1, 2, 4], [2, 4], [4] );
42 two_out_of_three( [4, 1], [2, 4], [1, 2] );
43 
44 sub two_out_of_three {
45    my ($array1, $array2, $array3) = @_;
46    print "Input: \@array1 = (" . join(", ", @$array1) . ")\n";
47    print "       \@array2 = (" . join(", ", @$array2) . ")\n";
48    print "       \@array3 = (" . join(", ", @$array3) . ")\n";
49    my @uniq_array1 = my_uniq(@$array1);
50    my @uniq_array2 = my_uniq(@$array2);
51    my @uniq_array3 = my_uniq(@$array3);
52    my %seen;
53    my @output = ();
54    foreach my $elem ( (@uniq_array1, @uniq_array2, @uniq_array3) ) {
55       $seen{$elem}++;
56    }
57    foreach my $found (sort {$a <=> $b} keys %seen) {
58       push @output, $found if $seen{$found} >= 2;
59    }
60    print "Output: (" . join(", ", @output) . ")\n";
61 }
62 
63 sub my_uniq {
64    my @array = @_;
65    my $found = {};
66    map { $found->{$_}++ } @array;
67    return keys %$found;
68 }