Re: Transposition of each letter pair in string
by sauoq (Abbot) on Dec 27, 2002 at 06:34 UTC
|
my $string = 'thisisatest';
for my $i (0 .. length($string)-2) {
(my $tmp = $string) =~ s/(.{$i})(.)(.)/$1$3$2/;
print $tmp, "\n";
}
-sauoq
"My two cents aren't worth a dime.";
| [reply] [d/l] |
Re: Transposition of each letter pair in string
by BrowserUk (Patriarch) on Dec 27, 2002 at 09:04 UTC
|
$string = 'thisIsATest'
(substr( $a = $string, $_, 2)) =~ s/(.)(.)/$2$1/
, print $a . $/
for (0 .. length($string) - 2)
htisIsATest
tihsIsATest
thsiIsATest
thiIssATest
thissIATest
thisIAsTest
thisIsTAest
thisIsAeTst
thisIsATset
thisIsATets
Examine what is said, not who speaks. | [reply] [d/l] |
Re: Transposition of each letter pair in string (one way)
by tye (Sage) on Dec 27, 2002 at 07:14 UTC
|
#!/usr/bin/perl -w
use strict;
$_= "thisisatest";
print "$_:\n";
while( /(.)(?=(.))/g ) {
print substr( $_, 0, pos($_)-1 ),
$2, $1, substr( $_, pos($_)+1 ), $/;
}
Rewording the description in a manner that helped at least one person understand: Take a string, pick any pair of consecutive letters in the string (at random), swap them. What is the list of all possible results?
- tye | [reply] [d/l] |
Re: Transposition of each letter pair in string
by Zaxo (Archbishop) on Dec 27, 2002 at 03:47 UTC
|
Here's a Perl regexical way:
s/(.)(.)/$2$1/g;
Update: If you must exchange them one by one to percolate the first character over to the last, I won't help. I'd just say:
s/(.)(.*)/$2$1/;
That's fairly close to my original.
Update2: What you say doesn't describe what you have. Nevermind, I'll let the psychics figure it out.
After Compline, Zaxo
| [reply] [d/l] [select] |
|
|
That doesn't match his example very well. I would think it was a fine solution except he said his example works. His example seems to return (or print really) a list consisting of every possible reversal of a single pair of neighboring letters. I.e. transposition_list('foobar') would be the list ('ofobar', 'foobar', 'foboar', 'foobra'). I'm not sure how to handle double letters like the 'oo' in 'foo' but his doesn't handle them specially.
I don't know if I really would do it this way but here is my untested first crack at it:
print "$_\n" for transposition_list('thisisatest');
sub transposition_list {
my $string = shift;
my @transpositions;
for my $i (0 .. length($string)-2) {
(my $tmp = $string) =~ s/(.{$i})(.)(.)/$1$3$2/;
push @transpositions, $tmp;
}
return @transpositions;
}
-sauoq
"My two cents aren't worth a dime.";
| [reply] [d/l] |
Re: Transposition of each letter pair in string
by John M. Dlugosz (Monsignor) on Dec 27, 2002 at 04:50 UTC
|
I think Zaxo's code is not doing the same thing. He is reversing each pair, and you are moving the first letter through each position in turn, and using each intermediate step. There is a nice Perlish way to find in a loop and process each in turn, but it doesn't work with s///. You might be able to simplify your code a little, but trying to get a regex to do it would be more obscure than what you have now. | [reply] |
Re: Transposition of each letter pair in string
by gjb (Vicar) on Dec 27, 2002 at 11:58 UTC
|
A bit nasty, since I'm fiddling with the pos, but it does the trick without modifying the original string and temp variables:
my $str = "thisisatest";
while ($str =~ /(.)(.)/g) {
print "$`$2$1$'\n";
pos($str)--;
}
Just my 2 cents, -gjb-
| [reply] [d/l] [select] |
Re: Transposition of each letter pair in string
by Aristotle (Chancellor) on Dec 27, 2002 at 23:54 UTC
|
I'm surprised noone mentioned reverse. Here's a slightly insidious solution.
use strict;
use warnings;
use Test::More q(no_plan);
my $string = "thisisatest";
for my $i (0 .. (length($string) - 2)) {
my @t = ($string)x2;
# original
substr($t[0], $i, 1) = substr($string, $i + 1, 1);
substr($t[0], $i + 1, 1) = substr($string, $i, 1);
# mine
$_ = reverse $_ for substr($t[1], $i, 2);
is($t[0], $t[1], "$t[0] eq $t[1]");
}
__END__
ok 1 - htisisatest eq htisisatest
ok 2 - tihsisatest eq tihsisatest
ok 3 - thsiisatest eq thsiisatest
ok 4 - thiissatest eq thiissatest
ok 5 - thissiatest eq thissiatest
ok 6 - thisiastest eq thisiastest
ok 7 - thisistaest eq thisistaest
ok 8 - thisisaetst eq thisisaetst
ok 9 - thisisatset eq thisisatset
ok 10 - thisisatets eq thisisatets
1..10
It relies on the fact that for aliases rather than copies its variable - and substr returns an Lvalue you can assign to, so that snippet is the equivalent of the more verbose substr($t[1],$i,2) = reverse substr($t[1],$i,2);.
That is, in my opinion, the most Perlish solution.
Makeshifts last the longest. | [reply] [d/l] [select] |
Re: Transposition of each letter pair in string
by pg (Canon) on Dec 27, 2002 at 04:37 UTC
|
There is a big discussion going on in the chat room, about this thread, as there are several different interpretations of what the author is actually trying to do.
As for whether there is a more perlier way, I would say, any solution that solves the problem, looks normal, easy to understand would be a good one.
| [reply] |
|
|
"01234567"
the list would be
('10234567',
'02134567',
'01324567',
'01243567',
'01235467',
'01234657',
'01234576')
Notice that the list will always contain one less element than the number of characters in the original string.
I agree that his English explanation would seem to suggest Zaxo's solution. His code, however, suggests the above explanation.
-sauoq
"My two cents aren't worth a dime.";
| [reply] [d/l] [select] |
|
|
-sauoq
"My two cents aren't worth a dime.";
| [reply] |
Re: Transposition of each letter pair in string
by Juerd (Abbot) on Dec 29, 2002 at 03:31 UTC
|
$\ = "\n";
my $foo = 'thisisatest';
print for map {
substr((my $bar = $foo), $_, 2, reverse substr $foo, $_, 2);
$bar;
} 0 .. -2 + length $foo;
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] [d/l] |
|
|
++, but why the complicated map games? :)
my $foo = 'thisisatest';
for(0 .. -2 + length $foo) {
substr((my $bar = $foo), $_, 2, reverse substr $foo, $_, 2);
print $bar, $/;
}
Makeshifts last the longest. | [reply] [d/l] |
|
|
++, but why the complicated map games? :)
I had it without "for" first. print takes a list, map creates one. It made sense. But it all was printed on one line, so I added -l and for to make it print every item on its own line.
When it functioned correctly, I pasted it in my web browser, and formatted it. Whenever you see me write $\ = "\n"; here, it's safe to assume I used only the command line to code and test, and used -l there.
If I were to rewrite it, I'd probably have map generate strings that include \n as follows:
my $foo = 'thisisatest';
print map {
substr((my $bar = $foo), $_, 2, reverse substr $foo, $_, 2);
"$bar\n";
} 0 .. -2 + length $foo;
map feels natural to me. I use it a lot, and love it.
- Yes, I reinvent wheels.
- Spam: Visit eurotraQ.
| [reply] [d/l] |
|
|
Re: Transposition of each letter pair in string
by grexman (Beadle) on Dec 27, 2002 at 16:20 UTC
|
Hello,
Here is my suggestions..
$string = "thisisatest";
@a=split //,$string;
foreach (0..(@a-2))
{
($a[$_],$a[$_+1])=($a[$_+1],$a[$_]);
print @a."\n";
($a[$_],$a[$_+1])=($a[$_+1],$a[$_]);
}
Ciao, Gregor
(Edit: forgot newline) | [reply] [d/l] |
Re: Transposition of each letter pair in string
by Cody Pendant (Prior) on Dec 27, 2002 at 22:51 UTC
|
Sorry about any confusion I may have caused.
My code above did work, but I felt it was clunky and wondered about other approaches, that was all.
For the record, the task was, as achieved above, to produce the array of results generated when you transpose each consecutive pair of adjacent letters: "test" becomes "etst, tset, tets" as first the t and e are transposed, then the e and s, then the s and t -- and the results were just fine. It was just the approach that I wanted you guys to comment on or show me alternatives to.
--
($_='jjjuuusssttt annootthheer
pppeeerrrlll haaaccckkeer')=~y/a-z//s;print;
| [reply] [d/l] |
Re: Transposition of each letter pair in string
by pizza_milkshake (Monk) on Dec 29, 2002 at 03:18 UTC
|
perl -le'$s="thisisatest";map{$t=$s;(substr($t,$_,1),substr($t,$_+1,1)
+)=(substr($t,$_+1,1),substr($t,$_,1));print $t}0..length($s)-2'
perl -e'$_=q#: 13_2: 12/"{>: 8_4) (_4: 6/2"-2; 3;-2"\2: 5/7\_/\7: 12m m::#;s#:#\n#g;s#(\D)(\d+)#$1x$2#ge;print'
| [reply] [d/l] |
|
|
| [reply] [d/l] [select] |