You are right, the regex is quicker but not the quickest. That honour goes davido's and fenLisesi's substr methods which are neck and neck. My split, splice and join gets the wooden spoon, being desperately slower than any other method.

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


In reply to Re^2: What is the best solution to swap input data? by johngg
in thread What is the best solution to swap input data? by bh_perl

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.