perl tr and ruby String#tr

S

snacktime

This, in perl:
$str =~ tr/\0\200/\200\0/;

Produces a different result then this:

str.tr!("\0\200","\200\0")

How do I do this in ruby?
 
R

Robert Klemme

snacktime said:
This, in perl:
$str =~ tr/\0\200/\200\0/;

Produces a different result then this:

str.tr!("\0\200","\200\0")

How do I do this in ruby?

Input data? Output data? Expected results?

robert
 
S

snacktime

my $even_bits = "\0";
my $odd_bits = "\200";
foreach (0 .. 7) {
$even_bits .= $odd_bits;
$odd_bits = $even_bits;
$odd_bits =~ tr/\0\200/\200\0/;
}
print unpack("c*","$odd_bits");

Output:
-12800-1280-128-12800-128-1280-12800-1280-128-1280-12800-128-12800-1280-128-12800-128-1280-12800-128-12800-1280-128-1280-12800-1280-128-12800-
128-1280-12800-1280-128-1280-12800-128-12800-1280-128-1280-12800-1280-128-12800-128-1280-12800-128-12800-1280-128-12800-128-1280-12800-1280-12
8-1280-12800-128-12800-1280-128-12800-128-1280-12800-128-12800-1280-128-1280-12800-1280-128-12800-128-1280-12800-128-12800-1280-128-12800-128-
1280-12800-1280-128-1280-12800-128-12800-1280-128-1280-12800-1280-128-12800-128-1280-12800-1280-128-1280-12800-128-12800-1280-128-12800-128-12
80-12800-128-12800-1280-128-1280-12800-1280-128-12800-128-1280-12800-128

even_bits = "\0"
odd_bits = "\200"
8.times do
even_bits << odd_bits
odd_bits = even_bits
odd_bits.tr!("\0\200","\200\0")
end

print odd_bits.unpack('c*')

Output:
0-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-
1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-12
80-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280
-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1
280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-1280-128
 
J

Jan Svitok

even_bits = "\0"
odd_bits = "\200"
8.times do
even_bits << odd_bits
odd_bits = even_bits
odd_bits.tr!("\0\200","\200\0")
end

print odd_bits.unpack('c*')

- odd_bits = even_bits
+ odd_bits = even_bits.clone

= assigns reference to the object in this case
 
J

Jan Svitok

Ok now I feel stupid:) Thanks for pointing that out.

Well, I looked at it for quite a long time before I realized what's
going on: at first I replaced your strings with 'A's and 'B's as these
are easier to recognize, then I tried 'AA-AB-BA-BB'.tr(...) and both
versions were ok. So it wasn't a tr problem. Soon after that the
inspiration came... ;-)

You're welcome.

J.
 
S

snacktime

Ok almost there one more question on using tr. If the to_string is a
variable, what to do? In perl you would use eval because the
transliteration for the from_string and to_string are done at compile
time. Following is the perl code that produces the correct result,
and the ruby code which I can't get to produce the same output. Any
ideas on how to do this correctly in ruby?


$even_parity = '\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\
245\246\47\50\251\252\53\254\55\56\2570\261\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\3
27\330YZ\333\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377\0\201\202\3\204\5\6\207\
210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\245\246\47\50\251\252\53\254\55\56\2570\2
61\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341\342c\34
4ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377';

eval <<EDQ;

sub setEvenParity {
my(\@s) = \@_;
foreach (\@s) {
tr/\\0-\\377/$even_parity/;
}
wantarray ? \@s : join '', \@s;
}

EDQ
die $@ if $@;

$out = setEvenParity('s');
print $out;


@even_parity = '\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\
245\246\47\50\251\252\53\254\55\56\2570\261\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\3
27\330YZ\333\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377\0\201\202\3\204\5\6\207\
210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\245\246\47\50\251\252\53\254\55\56\2570\2
61\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341\342c\34
4ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377';

eval <<EDQ

def setEvenParity(str)
str.tr("\\0-\\377",@even_parity)
end

EDQ

out = setEvenParity('s')
print out
 
M

Mike Stok

Ok almost there one more question on using tr. If the to_string is a
variable, what to do? In perl you would use eval because the
transliteration for the from_string and to_string are done at compile
time. Following is the perl code that produces the correct result,
and the ruby code which I can't get to produce the same output. Any
ideas on how to do this correctly in ruby?


$even_parity = '\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17
\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42
\243\44\
245\246\47\50\251\252\53\254\55\56\2570\261\2623\26456\267\2709\72
\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S
\324UV\3
27\330YZ\333\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o
\360qr\363t\365\366wx\371\372\173\374\175\176\377\0\201\202\3\204\5
\6\207\
210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232
\33\234\35\36\237\240\41\42\243\44\245\246\47\50\251\252\53\254\55
\56\2570\2
61\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311
\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341
\342c\34
4ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175
\176\377';

eval <<EDQ;

sub setEvenParity {
my(\@s) = \@_;
foreach (\@s) {
tr/\\0-\\377/$even_parity/;
}
wantarray ? \@s : join '', \@s;
}

EDQ
die $@ if $@;

$out = setEvenParity('s');
print $out;


@even_parity = '\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17
\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42
\243\44\
245\246\47\50\251\252\53\254\55\56\2570\261\2623\26456\267\2709\72
\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S
\324UV\3
27\330YZ\333\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o
\360qr\363t\365\366wx\371\372\173\374\175\176\377\0\201\202\3\204\5
\6\207\
210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232
\33\234\35\36\237\240\41\42\243\44\245\246\47\50\251\252\53\254\55
\56\2570\2
61\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311
\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341
\342c\34
4ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175
\176\377';

eval <<EDQ

def setEvenParity(str)
str.tr("\\0-\\377",@even_parity)
end

EDQ

out = setEvenParity('s')
print out

Have you tried the seemingly simple approach like this, which avoids
eval:

ratdog:~ mike$ irb --prompt simple=> "banana"

Maybe I am misunderstanding what you want to do...

Hope this helps,

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
S

snacktime

Have you tried the seemingly simple approach like this, which avoids
eval:

ratdog:~ mike$ irb --prompt simple
=> "banana"

Yes I tried it without eval also, but it won't produce the same output
as the perl code. I've tried every incantation I can think of but no
luck. I'm checking my results by comparing them to the output of
perl's String::parity. The perl code I posted is basically an
abbreviation of what String::parity does when setting even parity.
It's the last bit in this damn module I'm working on also:) If I get
this figured out I'll be done.
 
S

snacktime

Here is a shortened version. the ruby and perl code do not produce
the same output. I want the ruby version to produce the same output
as the perl version.

In perl:

$str = "s";
$str =~ tr/\0-\377/\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243
\44\245\246\47\50\251\252\53\254\55\56\2570\261\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324
UV\327\330YZ\333\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377\0\201\202\3\204\5\6\
207\210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\245\246\47\50\251\252\53\254\55\56\25
70\261\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341\342
c\344ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377/;

In ruby:

's'.tr!("\0-\377","\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243
\44\245\246\47\50\251\252\53\254\55\56\2570\261\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324
UV\327\330YZ\333\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377\0\201\202\3\204\5\6\
207\210\11\12\213\14\215\216\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\245\246\47\50\251\252\53\254\55\56\25
70\261\2623\26456\267\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341\342
c\344ef\347\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377")
 
M

Mike Stok

Yes I tried it without eval also, but it won't produce the same output
as the perl code. I've tried every incantation I can think of but no
luck. I'm checking my results by comparing them to the output of
perl's String::parity. The perl code I posted is basically an
abbreviation of what String::parity does when setting even parity.
It's the last bit in this damn module I'm working on also:) If I get
this figured out I'll be done.

Can you give me a hint as to what doesn't work? For a simple upper
case subset of your code (using double quotes) I see

ratdog:~ mike$ irb --prompt simple\324UV\327\330YZ"
=> "AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ"=> "ABA\303AB"

seems pretty reasonable - can you show a simple example of what
doesn't behave as you want?

Hmm, thinking about it, when you do the Ruby eval, are uou missing
quotes around @even_parity?

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
S

snacktime

Can you give me a hint as to what doesn't work? For a simple upper
case subset of your code (using double quotes) I see

I'm implementing string parity functions using perl's String::parity
as the base to work from. I'm assuming that the ruby code is working
as it was designed to, but I want to find out what I need to do to
make it work like the perl example. I just posted a shorter, easier
to test version. The perl version outputs a string correctly set to
even parity. The ruby code doesn't. I've tried quotes, no quotes,
double quotes, eval, beating my head in the wall, all of that. It's
something else I am missing.

Chris
 
M

Mike Stok

I'm implementing string parity functions using perl's String::parity
as the base to work from. I'm assuming that the ruby code is working
as it was designed to, but I want to find out what I need to do to
make it work like the perl example. I just posted a shorter, easier
to test version. The perl version outputs a string correctly set to
even parity. The ruby code doesn't. I've tried quotes, no quotes,
double quotes, eval, beating my head in the wall, all of that. It's
something else I am missing.

Chris

I think it's due to multiple interpolations - first in double quotish
context and then as a pattern for tr, where \ and - are the only real
metacharacters.

Looks like you need to do something like use \\\55 in place of \55 (a
- character) and \\\134 in place of \134 (a \ character)

Ick.

Program and output below

#!/usr/bin/env ruby

str = "()*+,-./09AZ[_]abcpqrstuvwxyz\376"
p str
str.tr!("\0-\377","\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216
\17\220\21\22\223\24\225\226\27\30\231\232\33\234\35\36\237\240\41\42
\243\44\245\246\47\50\251\252\53\254\\\55\56\2570\261\2623\26456\267
\2709\72\273\74\275\276\77\300AB\303D\305\306GH\311\312K\314MN\317P
\321\322S\324UV\327\330YZ\333\\\134\335\336_\140\341\342c\344ef\347
\350ij\353l\355\356o\360qr\363t\365\366wx\371\372\173\374\175\176\377
\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17\220\21\22\223\24
\225\226\27\30\231\232\33\234\35\36\237\240\41\42\243\44\245\246\47\50
\251\252\53\254\\\55\56\2570\261\2623\26456\267\2709\72\273\74\275\276
\77\300AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ
\333\\\134\335\336_\140\341\342c\344ef\347\350ij\353l\355\356o\360qr
\363t\365\366wx\371\372\173\374\175\176\377")
p str

output:

"()*+,-./09AZ[_]abcpqrstuvwxyz\376"
"(\251\252+\254-.\25709AZ\333_\335\341\342c\360qr\363t\365\366wx\371
\372~"

Hope this helps,

Mike

--

Mike Stok <[email protected]>
http://www.stok.ca/~mike/

The "`Stok' disclaimers" apply.
 
S

snacktime

I figured out the problem. Ruby tr doesn't handle octal numbers like
perl does. Not sure if it's just not implemented or maybe there is a
correct way to do it I'm not sure of. In any case instead of trying
to use tr to map the octal numbers I just made an array of decimal
numbers for the even bit map and then made this function. Works fine.


def setEvenParity(str)
new = []
str.each_byte {|b| new << @even_parity}
new.pack("C*")
end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,209
Messages
2,571,088
Members
47,687
Latest member
IngridXxj

Latest Threads

Top