lokiloki has asked for the wisdom of the Perl Monks concerning the following question:

Here is my sample code...
#!/usr/bin/perl srand(time); #option 1 my @a = ("b","c","d","e","f","g","h","i","j"); my $a = "aaaaaaaaaaaaaaaaaaaaaa"; $a =~ s/a/$a[int(rand(@a))]/g; print "\noption 1:\n$a\n"; #option 2 my @b = ("b","c","d","e","f","g","h","i","j"); my $b = "bbbbbbbbbbbbbbbbbbbbb"; $b =~ s/b/randme()/ge; print "\noption 2:\n$b\n"; sub randme { return $b[int(rand(@b))]; } #option 3 my @c = ("b","c","d","e","f","g","h","i","j"); my $c = "ccccccccccccccccccc"; for (;;) { last unless $c =~ s/c/$c[int(rand(@c))]/; } print "\noption 3:\n$c\n";
And here are the results...
option 1: bbbbbbbbbbbbbbbbbbbbbb option 2: gjfcijeeddgbcghddjjff option 3: dbjdbhbhdbedfdeifdb
Why on earth won't option 1 return random letters, especially since option 2 will?! This doesn't make logical sense to my poorly constructed brain.

And is there a better way to do what I am looking to do (the results of 2 or 3 above)?

Replies are listed 'Best First'.
Re: randomizing global replacement
by GrandFather (Saint) on Jan 30, 2007 at 04:04 UTC

    You left the /e off the regex:

    use strict; use warnings; my @a = ('b' .. 'j'); my $str = 'a' x 23; $str =~ s/a/$a[rand@a]/ge; print "$str\n";

    Prints:

    dbjgcegjgieigecihebhdih

    Oh, and don't use $a as a general purpose variable - it's magical ;)


    DWIM is Perl's answer to Gödel
      Thank you.

      Incidentally, the use of rand@a is something I have never seen before. My version of the Programming Perl book makes no mention of such usage of this as an alternative to $a[int(rand(@a))]... when did this alternative come into being?

        rand@a is just rand(@a) without the optional (). @ can't be part of the word beginning "rand", because it isn't a valid identifier character, so it's treated as a new token. The int() isn't necessary since array elements are automatically int'd (e.g. $a[3.14] automatically gets you $a[3]).
Re: randomizing global replacement
by xdg (Monsignor) on Jan 30, 2007 at 04:13 UTC

    Have you looked closely at the modifiers after each substitution? For example, add an "e" to option 1.

    $a =~ s/a/$a[int(rand(@a))]/ge;

    Or, perhaps better yet, take it away from option 2.

    $b =~ s/b/randme()/g;

    Result:

    option 1: heebdjfjiecbieiebdfddi option 2: randme()randme()randme()randme()randme()randme()randme()randme() randme()randme()randme()randme()randme()randme()randme()randme() randme()randme()randme()randme()randme()

    See perlop for the meaning of the flags and some examples.

    -xdg

    Code written by xdg 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.