Re: What is the best solution to swap input data?
by GrandFather (Saint) on Nov 09, 2006 at 06:58 UTC
|
use strict;
use warnings;
my $str = '12345678';
$str =~ s/(.)(.)/$2$1/g;
print $str;
Prints:
21436587
Update: BTW, using $a and $b as variables is a bad idea. They are the variables used by sort.
DWIM is Perl's answer to Gödel
| [reply] [d/l] [select] |
Re: What is the best solution to swap input data?
by ikegami (Patriarch) on Nov 09, 2006 at 07:28 UTC
|
GrandFather nailed it, so this isn't an answer to your question, but a comment on
$out = sprintf("@tmp");
It's wrong. Using sprintf will cause any % to be interpreted specially.
local $" = ''; # Don't insert spaces.
$out = "@tmp"; # sprintf not needed at all.
A better solution would be:
$out = join('', @tmp);
I've also noticed you've been putting your comments in <code>/<c> tags. Please don't do that. Only put code (and other pre-formatted data) in <code>/<c> tags. If the problem is that you don't know HTML, pretty much all you need to know is to put <p> at the start of every paragraph. | [reply] [d/l] [select] |
Re: What is the best solution to swap input data?
by davido (Cardinal) on Nov 09, 2006 at 07:41 UTC
|
GrandFather's solution is the most appropriate one I can think of, but there's something about (.)(.) that bugs me. ...no, not for any good reason. ;)
So here's an inferior solution that doesn't annoy me with (.)(.) (those beady eyes).
my $data = '123456789';
$data =~ s/(.{2})/reverse $1/eg;
print $data, "\n";
You didn't define what happens if the string has an uneven number of characters. The most likely alternative is to do nothing with that extra digit at the end. ...but maybe you would prefer doing nothing with the leading digit, in the case of an uneven number of digits, or maybe you'd prefer to fail altogether. ...just some things to consider...
In case you're wondering why this solution is inferior, here's a small list:
- reverse $1 is more verbose than $2$1
- s///eg performs a string eval, which is less efficient than $2$1, and more prone to programmer error.
- (.{2}) is possibly harder to read than (.)(.), even if it's less annoying looking.
- In case you haven't guessed, this whole commentary should be taken tongue in cheek.
Update:
The OP's original solution used substr, and since I was in the mood to tinker, I decided to work up my own substr version:
use strict;
use warnings;
my $data = '123456789';
my $output = '';
my $position = 0;
while ( $position < length $data ) {
$output .= reverse substr $data, $position, 2;
$position += 2;
}
print $output, "\n";
| [reply] [d/l] [select] |
|
|
Here's a substr solution that works in situ:
my $data = '123456789';
foreach (my $i = 0; $i + 1 < length $data; $i += 2) {
substr($data, $i, 2) = reverse substr($data, $i, 2);
}
print $data, "\n";
__END__
214365879
| [reply] [d/l] |
|
|
That's fenLisesi's solution here in this thread, only using an assignment instead of the 4-arg form of substr.
-- Hofmator
Code written by Hofmator and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.
| [reply] |
Re: What is the best solution to swap input data?
by fenLisesi (Priest) on Nov 09, 2006 at 07:52 UTC
|
A few minor points that caught my attention:
- $a and $b are not the best variable names, as they are special
- You could use the replacement capability of substr to eliminate some temp vars
- In general, it is a good idea to unload args to a function as early as possible, so the shift statement would better become the first line
- It is a good idea to limit the scope of your vars as much as possible, so my ($a, $b) would be closer to home inside the for loop
sub swap {
my ($str) = @_;
die 'No input?' unless defined $str;
## 0 to half-length minus one
for my $i (0 .. (length( $str ) >> 1) - 1) {
my $j = $i << 1;
substr( $str, $j, 2, reverse substr( $str, $j, 2 ) );
}
return $str;
}
Cheers.
Update: Took sub swap {...} out of readmore | [reply] [d/l] [select] |
Re: What is the best solution to swap input data?
by johngg (Canon) on Nov 09, 2006 at 11:39 UTC
|
I think that GrandFather's regular expression solution is the best for you but you ask what other solutions we have. davido has come up with an improved substr solution. Here's a way with split, splice and join.
use strict;
use warnings;
my $str = q{12345678};
print qq{$str\n};
$str = revByGroup($str);
print qq{$str\n};
sub revByGroup
{
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;
}
and the output is
12345678
21436587
It copes with an odd numer of characters, leaving the last odd character at the end of the string. I hope this is of interest. Cheers, JohnGG | [reply] [d/l] [select] |
Re: What is the best solution to swap input data?
by swampyankee (Parson) on Nov 09, 2006 at 15:27 UTC
|
You can also do this with split, although my implementation is not quite optimal.
#!/usr/bin/perl
use strict;
use warnings;
while(<DATA>){
chomp;
my $in = $_;
my @pairs = split(/(.{2})/);
$_ = reverse foreach @pairs;
my $out = join('', @pairs);
print "in: $in => out: $out\n";
}
__DATA__
12345678
1234
12
1234
123456
87654321
Outputs:
in: 12345678 => out: 21436587
in: 1234 => out: 2143
in: 12 => out: 21
in: 1234 => out: 2143
in: 123456 => out: 214365
in: 87654321 => out: 78563412
As I said, I'm quite sure that this is far from optimal, as the regex is probably quicker, shorter, and at least as clear.
emc
At that time [1909] the chief engineer was almost always the chief test pilot as well. That had the fortunate result of eliminating poor engineering early in aviation.
—Igor Sikorsky, reported in AOPA Pilot magazine February 2003.
| [reply] [d/l] [select] |
|
|
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
I hope this is of interest. Cheers, JohnGG | [reply] [d/l] [select] |
|
|
| [reply] |
| A reply falls below the community's threshold of quality. You may see it by logging in. |