Perl Christmas Quiz

Hakim Cassimally hakim.cassimally at gmail.com
Fri Dec 12 13:18:24 GMT 2008


On 12/12/2008, Paul Makepeace <paulm at paulm.com> wrote:
> SPOILERS contd

> >> 3) Write a Perl function that takes two references to arrays and returns the intersect of them. If an entry appears n times in array 1 and m times in array 2, the output should list that entry min(n,m) times. Bonus mark for one line solutions.
>  >
>  > use Set::Scalar;
>  > sub intersect (\@\@) {
>  >  my ($a1, $a2) = map { Set::Scalar->new(@$_) } @_;
>  >  my $intersection = $a1 * $a2;
>  >  return $intersection->elements;
>  > }
>
>
> This isn't a set question though. Sets have unique membership,

The question isn't specific about how the output should look if it a
key doesn't appear in both arrays, or if n==m.  But here's my attempt:

sub uniqc { my %seen; $seen{$_}++ for @_; \%seen }
sub intersect {
    my @lists = map uniqc(@$_), @_;
    my $all = uniqc map @$_, @_;
    return { map {
        my $key = $_;
        my @vals = grep $_, map { $_->{$key} } @lists;
        my $val = @vals == 1 ?
            $vals[0]
          : do {
                join '-' => (sort {$a<=>$b} @vals)[0,-1];
                };
          $key => $val;
        } keys %$all };
}

# to test:
my @x = qw/ bar      foo foo  baz /;
my @y = qw/ bar bar  foo          /;
say Dumper(intersect( \@x, \@y ));

__END__
$VAR1 = {
          'bar' => '1-2',
          'baz' => 1,
          'foo' => '1-2'
        };


More information about the london.pm mailing list