Perl tr and ruby String#tr

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?

snacktime [email protected] wrote:

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

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

On 8/12/06, snacktime [email protected] wrote:

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

On 8/12/06, Jan S. [email protected] wrote:

print odd_bits.unpack(‘c*’)

  • odd_bits = even_bits
  • odd_bits = even_bits.clone

= assigns reference to the object in this case

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

On 8/12/06, snacktime [email protected] wrote:

print odd_bits.unpack(‘c*’)

  • odd_bits = even_bits
  • odd_bits = even_bits.clone

= assigns reference to the object in this case

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… :wink:

You’re welcome.

J.

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 [email protected] if [email protected];

$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

On 12-Aug-06, at 10:32 PM, snacktime wrote:

\243\44
\312K\314MN\317P\321\322S\324UV\327\330YZ\333\134\335\336_\140\341
}
@even_parity = '\0\201\202\3\204\5\6\207\210\11\12\213\14\215\216\17
\56\2570\2
end

EDQ

out = setEvenParity(‘s’)
print out

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

ratdog:~ mike$ irb --prompt simple

@upper_case = ‘ABCDEFGHIJKLMNOPQRSTUVWXYZ’
=> “ABCDEFGHIJKLMNOPQRSTUVWXYZ”

def uc(s)
s.tr(‘abcdefghijklmnopqrstuvwxyz’, @upper_case)
end
=> nil

uc(‘banana’)
=> “BANANA”

@upper_case = ‘abcdefghijklmnopqrstuvwxyz’
=> “abcdefghijklmnopqrstuvwxyz”

uc(‘banana’)
=> “banana”

Maybe I am misunderstanding what you want to do…

Hope this helps,

Mike

Mike S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.

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")

uc(‘banana’)
=> “BANANA”

@upper_case = ‘abcdefghijklmnopqrstuvwxyz’
=> “abcdefghijklmnopqrstuvwxyz”

uc(‘banana’)
=> “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.

On 12-Aug-06, at 11:19 PM, snacktime wrote:

uc(‘banana’)
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

@even_parity = “AB\303D\305\306GH\311\312K\314MN\317P\321\322S
\324UV\327\330YZ”
=> “AB\303D\305\306GH\311\312K\314MN\317P\321\322S\324UV\327\330YZ”

@even_parity.length
=> 26

def setEvenParity(s)
s.tr(‘A-Z’, @even_parity)
end
=> nil

setEvenParity(‘ABACAB’)
=> “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 S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.

On 12-Aug-06, at 11:44 PM, snacktime wrote:

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 S. [email protected]
http://www.stok.ca/~mike/

The “`Stok’ disclaimers” apply.

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

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[b]}
new.pack(“C*”)
end

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs