[Date Prev][Date Next][Thread Prev][Thread Next] [Search] [Date Index] [Thread Index]

Re: [FWP] Interleaving arrays



On Wed, Nov 10, 1999 at 01:19:29PM -0600, Bennett Todd wrote:
> 1999-11-10-13:30:18 tomr@aceldama.com:
> > 
> >    @cats = @cats[map (($_/2 + ($_ % 2) * $#cats/2), 0..$#cats)];
> > 
> > [...] Anyone else have comments?
> 
> You are a sick little monkey. I like that. :-)
> 
> Seriously, this is something I frequently need to do, and I've never
> seen such
> a lovely way of saying it. Next natural question would be, does it keep
> working for ncols!=2. Looks to me like it does. 

Are you sure?  It tried a simple case (1..9) and it didn't.  5 was
repeated and 9 was lost.  The following adjustment took care of it,
though:

   @cats = @cats[map (($_/2 + ($_ % 2) * ($#cats/2 + 1)), 0..$#cats)];
                                         ^        ^^^^^

Oddly, benchmarking indicates that Tom's way is about twice as fast as
mine, which was:

  my $half = $#cats/2;
  @cats = @cats[map (($_, $_+$half+1), 0..$half)];

Knowing next to nothing about Perl internals, I'm guessing that it's
something to do with growing the list at each iteration of the map.

Implementing the optimization Tom mentioned:

  my $half = $#cats/2;
  @cats = @cats[map (($_/2 + ($_ % 2) * ($half + 1)), 0..$#cats)];

results in a pretty substantial speedup (almost 25%).

Here are the numbers, in case anyone is interested:

  Benchmark: timing 100 iterations of Mine, Tom's, Tom's improved...
        Mine: 44 wallclock secs (41.43 usr +  0.04 sys = 41.47 CPU)
       Tom's: 24 wallclock secs (22.20 usr +  0.00 sys = 22.20 CPU)
  Tom's improved: 17 wallclock secs (16.93 usr +  0.00 sys = 16.93 CPU)

And here's the code:

  #!/usr/local/bin/perl -w
  use strict;
  use Benchmark;

  my @array = (0..8000);

  sub mine {
    my $half = $#array/2;
    map (($_, $_+$half+1), 0..$half);
  }

  sub toms {
    map (($_/2 + ($_ % 2) * ($#array/2 + 1)), 0..$#array);
  }

  sub toms_opt {
    my $half = $#array/2;
    map (($_/2 + ($_ % 2) * ($half + 1)), 0..$#array);
  }

  timethese(100, {"Mine" => \&mine, 
                  "Tom's" => \&toms, 
                  "Tom's improved" => \&toms_opt});


==== Want to unsubscribe from Fun With Perl?  Well, if you insist...
==== Send email to <fwp-request@technofile.org> with message _body_
====   unsubscribe