in reply to Re: What is the best solution to swap input data?
in thread What is the best solution to swap input data?
I had also come up with almost the same method as your's but using a map rather than storing in an array. Your version is slightly the faster. One way of speeding both up is to grep out the empty elements that result from the split. The benchmark code first works on a short odd-length string to check that all methods produce the same result. Then methods are compared with a longer string. Here's the results
reRev - 214365879 reSwap - 214365879 spliceSwap - 214365879 splitMap - 214365879 splitMapGrep - 214365879 splitRev - 214365879 splitRevGrep - 214365879 substrRev - 214365879 substrSubstr - 214365879 twoSubstrs - 214365879 Rate SpliceSwap SplitMap SplitRev TwoSubstrs SplitMapGr +ep SplitRevGrep ReRev ReSwap SubstrRev SubstrSubstr SpliceSwap 4.15/s -- -64% -68% -70% -7 +1% -72% -84% -85% -89% -89% SplitMap 11.7/s 181% -- -9% -17% -1 +9% -22% -54% -59% -68% -68% SplitRev 12.8/s 209% 10% -- -8% -1 +1% -14% -50% -55% -65% -65% TwoSubstrs 14.0/s 237% 20% 9% -- - +3% -7% -45% -50% -62% -62% SplitMapGrep 14.4/s 247% 23% 13% 3% +-- -4% -44% -49% -61% -61% SplitRevGrep 15.0/s 261% 28% 17% 7% +4% -- -42% -47% -59% -59% ReRev 25.6/s 517% 119% 100% 83% 7 +8% 71% -- -9% -30% -30% ReSwap 28.3/s 580% 142% 120% 102% 9 +6% 89% 10% -- -23% -23% SubstrRev 36.7/s 785% 214% 187% 162% 15 +5% 145% 43% 30% -- -0% SubstrSubstr 36.9/s 788% 215% 188% 163% 15 +6% 146% 44% 30% 0% --
and here's the code
use strict; use warnings; use Benchmark qw{cmpthese}; my $str = q{123456789}; print q{reRev - }, reRev($str), qq{\n}; print q{reSwap - }, reSwap($str), qq{\n}; print q{spliceSwap - }, spliceSwap($str), qq{\n}; print q{splitMap - }, splitMap($str), qq{\n}; print q{splitMapGrep - }, splitMapGrep($str), qq{\n}; print q{splitRev - }, splitRev($str), qq{\n}; print q{splitRevGrep - }, splitRevGrep($str), qq{\n}; print q{substrRev - }, substrRev($str), qq{\n}; print q{substrSubstr - }, substrSubstr($str), qq{\n}; print q{twoSubstrs - }, twoSubstrs($str), qq{\n}; $str = $str x 1000; my $rcUseReRev = sub { my $ret = reRev($str); }; my $rcUseReSwap = sub { my $ret = reSwap($str); }; my $rcUseSpliceSwap = sub { my $ret = spliceSwap($str); }; my $rcUseSplitMap = sub { my $ret = splitMap($str); }; my $rcUseSplitMapGrep = sub { my $ret = splitMapGrep($str); }; my $rcUseSplitRev = sub { my $ret = splitRev($str); }; my $rcUseSplitRevGrep = sub { my $ret = splitRevGrep($str); }; my $rcUseSubstrRev = sub { my $ret = substrRev($str); }; my $rcUseSubstrSubstr = sub { my $ret = substrSubstr($str); }; my $rcUseTwoSubstrs = sub { my $ret = twoSubstrs($str); }; cmpthese (-3, { ReRev => $rcUseReRev, ReSwap => $rcUseReSwap, SpliceSwap => $rcUseSpliceSwap, SplitMap => $rcUseSplitMap, SplitMapGrep => $rcUseSplitMapGrep, SplitRev => $rcUseSplitRev, SplitRevGrep => $rcUseSplitRevGrep, SubstrRev => $rcUseSubstrRev, SubstrSubstr => $rcUseSubstrRev, TwoSubstrs => $rcUseTwoSubstrs, }); # davido's regexp reverse execute # sub reRev { my $str = shift; $str =~ s{(.{2})}{reverse $1}eg; return $str; } # GrandFather's regexp string substitution # sub reSwap { my $str = shift; $str =~ s{(.)(.)}{$2$1}g; return $str; } # johngg's original split, splice and join # sub spliceSwap { my $str = shift; my @chars = split m{}, $str; for (my $idx = 0; $idx < $#chars; $idx += 2) { splice @chars, $idx, 0, splice @chars, $idx + 1, 1; } return join q{}, @chars; } # johngg's split and reverse via map # sub splitMap { return join q{}, map { my $rev = reverse $_ } split m{(..)}, $_[0]; } # johngg's split and reverse via map with a # grep to remove empty elements from split # sub splitMapGrep { return join q{}, map { my $rev = reverse $_ } grep {$_} split m{(..)}, $_[0]; } # swampyankee's split and reverse of array # sub splitRev { my $str = shift; my @pairs = split m{(.{2})}, $str; $_ = reverse foreach @pairs; return join q{}, @pairs; } # swampyankee's split and reverse of array with # my grep tweak # sub splitRevGrep { my $str = shift; my @pairs = grep {$_} split m{(.{2})}, $str; $_ = reverse foreach @pairs; return join q{}, @pairs; } # davido's use of substr # sub substrRev { my $str = shift; my $rev = q{}; my $pos = 0; while ($pos < length $str) { $rev .= reverse substr $str, $pos, 2; $pos += 2; } return $rev; } # fenLisesi's without error checking so on same # footing as others # sub substrSubstr { my ($str) = @_; for my $i (0 .. (length( $str ) >> 1) - 1) { my $j = $i << 1; substr( $str, $j, 2, reverse substr( $str, $j, 2 ) ); } return $str; } # bh_perl's original tweaked with a join rather than # a sprintf plus changing for loop end test to cope # with odd characters # sub twoSubstrs { my $str = shift; my ($tmp1, $tmp2); my @tmp; for (my $idx=0; $idx < length $str; $idx += 2) { $tmp1 = substr $str, $idx, 1; $tmp2 = substr $str, $idx + 1, 1; push @tmp, $tmp2 . $tmp1; } my $out = join q{}, @tmp; return $out; }
I hope this is of interest.
Cheers,
JohnGG
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^3: What is the best solution to swap input data?
by swampyankee (Parson) on Nov 10, 2006 at 16:43 UTC |