Peter
Peter Campbell Smith

Count the unsorted
and two thirds is enough

Weekly challenge 229 — 7 August 2023

Week 229 - 7 Aug 2023

Task 2

Task — Two out of three

You are given three array of integers. Write a script to return all the elements that are present in at least 2 out of the 3 given arrays.

Examples


Example 1
Input: @array1 = (1, 1, 2, 4)
       @array2 = (2, 4)
       @array3 = (4)
Output: (2, 4)

Example 2
Input: @array1 = (4, 1)
       @array2 = (2, 4)
       @array3 = (1, 2)
Output: (1, 2, 4)

Analysis

My solution to this is first to construct a hash %present. I loop over the arrays using for $j (1 .. 3) and append $n to $present{$j} for every $n in $array$j.

So, for example 1 above, I will end up with:
$present{1} == '11' # there are 2 '1's in @array1
$present{2} == '23' # 2 is in @array2 and @array3
$present{4} == '12' # 4 is in @array1 and @array2

So now we can see that if $j appears in at least two arrays, $present{$j} will match one (or more) of '12', '13', or '23'. This will work even if $j appears more than once in a single array.

Try it 

Example: (1, 2, 3), (2, 3, 4), (4, 5, 6)

Script


#!/usr/bin/perl

use v5.16;    # The Weekly Challenge - 2023-08-07
use utf8;     # Week 229 task 2 - Two out of three
use strict;   # Peter Campbell Smith
use warnings; # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge

two_out_of_three([1, 1, 2, 4], [2, 4], [4]);
two_out_of_three([1, 3, 2], [3, 1, 2], [2, 1, 3]);
two_out_of_three([1, 2, 3], [4, 5, 6], [7, 8, 9]);

# random example
my ($j, @array1, @array2, @array3);
for $j (0 .. 9) {
    push @array1, int(rand(90));
    push @array2, int(rand(90));
    push @array3, int(rand(90));
}
two_out_of_three(\@array1, \@array2, \@array3);
        

sub two_out_of_three {
    
    my ($j, %present, $n, $good);
    
    # for each value v in array n appends an n to present{v}
    for $j (1 .. 3) {
        $present{$_} .= $j for @{$_[$j - 1]};
    }
    
    # if v is in at least two arrays, present{v} will contain 12, 23 or 13
    for $n (keys %present) {
        $good .= qq[$n, ] if $present{$n} =~ m!12|13|23!;
    }
    
    say qq[\nInput: \@array1 = (], join(', ', @{$_[0]}) . qq[)] .
        qq[\n       \@array2 = (], join(', ', @{$_[1]}) . qq[)] .
        qq[\n       \@array3 = (], join(', ', @{$_[2]}) . qq[)];
    say qq[Output: (] . ($good ? substr($good, 0, -2) : 'none') . qq[)];
    
}

Output


Input: @array1 = (1, 1, 2, 4)
       @array2 = (2, 4)
       @array3 = (4)
Output: (4, 2)

Input: @array1 = (1, 3, 2)
       @array2 = (3, 1, 2)
       @array3 = (2, 1, 3)
Output: (2, 1, 3)

Input: @array1 = (1, 2, 3)
       @array2 = (4, 5, 6)
       @array3 = (7, 8, 9)
Output: (none)

Input: @array1 = (21, 46, 63, 64, 86, 51, 23, 35, 29, 43)
       @array2 = (41, 28, 54, 72, 38, 7, 2, 6, 53, 19)
       @array3 = (34, 76, 9, 72, 47, 51, 53, 36, 75, 14)
Output: (53, 72, 51)