Perl Christmas Quiz
Abigail
abigail at abigail.be
Fri Dec 12 17:19:47 GMT 2008
On Fri, Dec 12, 2008 at 01:18:24PM +0000, Hakim Cassimally wrote:
> 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 };
> }
And my attempt:
# Takes 2 or more array refs as argument, returns the intersection.
use List::Util 'min';
sub intersect {
%_=();$==$_,map{$_{$_}[$=]++}@{$_[$=]}for+0..$#_;map{($_)x min@{$_{$_}}[0..$#_]}keys%_;
}
Abigail
More information about the london.pm
mailing list