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