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