in reply to How to transpose lines faster?

I would have used with_substr() (in the spoiler), but your chop-based is faster during my test. However, if the character '0' (ASCII 48) is in your possible alphabet, chop() won't give the right answer

benchmark:

#!/usr/bin/env perl -l use warnings; use strict; use Benchmark qw/timethese cmpthese/; use Test::More; my @az = ('a'..'z', 'A'..'Z', '1'..'9'); # note: if '0' is in your +alphabet, chop() will fail my @golden_original; my $N = 200; for( 1 .. $N ) { push @golden_original, join '', map { $az[rand @az] } 1..$N; } #print length($str), qq(\t"$str"); #print scalar @golden_original; #diag explain org => \@gold +en_original; my $wch = [with_chop (@golden_original)]; #diag explain wch => $wch; my $wsp = [with_split (@golden_original)]; #diag explain wsp => $wsp; my $wsu = [with_substr(@golden_original)]; #diag explain wsu => $wsu; is_deeply( $wsp, $wch, 'split vs chop'); is_deeply( $wsu, $wch, 'substr vs chop'); sub with_split { my @original = @_; my @transposed; for( @original ) { my $i = 0; $transposed[$i++] .= $_ for split //; } return @transposed; } sub with_chop { my @original = @_; my @transposed; for( map $_ = reverse, @original ){ my $i = 0; $transposed[ $i ++ ] .= chop while $_; } return @transposed; } sub with_substr { my @original = @_; my $w = scalar @original; my @transposed = ( ' 'x$w ) x $w; for my $i ( 0 .. $#original ) { for my $j ( 0 .. $i ) { substr($transposed[$i], $j, 1) = substr($original[$j], $i, + 1); substr($transposed[$j], $i, 1) = substr($original[$i], $j, + 1); } } return @transposed; } my $r = timethese( 1000, { with_substr => sub { with_substr( @golden_original ); }, with_split => sub { with_split ( @golden_original ); }, with_chop => sub { with_chop ( @golden_original ); }, }); cmpthese $r; done_testing();
with_chop: 5 wallclock secs ( 5.19 usr + 0.00 sys = 5.19 CPU) @ 19 +2.79/s (n=1000) with_split: 13 wallclock secs (13.14 usr + 0.02 sys = 13.16 CPU) @ 76 +.01/s (n=1000) with_substr: 7 wallclock secs ( 6.89 usr + 0.00 sys = 6.89 CPU) @ 1 +45.14/s (n=1000) Rate with_split with_substr with_chop with_split 76.0/s -- -48% -61% with_substr 145/s 91% -- -25% with_chop 193/s 154% 33% --

I am no good with pack/unpack, otherwise, I would have tested LanX's suggestion, too. From what I remember in past benchmarks, that pair usually beats substr.

update: chop will fail because you're testing the truthiness of the character it returns. '0', like 0, is false.

update 2: hmm, no, you should be testing the truthiness of the whole string. When I had '0' in my alphabet, it dropped one or more '0's from the last row of @$wch... Oh, right, if the last character in one of the strings in @original ends in one or more zeroes, then it will evaluate to false, rather than your expected true. So if '0' might be in your alphabet, you should probably test the if length($_) instead.

update 3: I meant while length $_...

Replies are listed 'Best First'.
Re^2: How to transpose lines faster?
by pryrt (Abbot) on Feb 01, 2018 at 22:23 UTC
      Thank you, pryrt, for nice analysis, and thanks for finding a bug with '0'.