in reply to Function over all letters in a string

TMWTOTDI, this one getting more milage out of each rand call:
{ my $r = substr rand, 2; sub crand() { length $r or $r = substr rand, 2; chop $r; } } s[(.)]{$1 x (1+crand/3)}ge;

Makeshifts last the longest.

Replies are listed 'Best First'.
Re: Function over all letters in a string
by Abigail-II (Bishop) on Dec 01, 2003 at 10:35 UTC
    It looks cute, but it's wrong. About once every 10,000 times, rand() returns a number that's smaller than 0.0001, and that gets represented in scientific notation, meaning there are an 'e' and a '-' in the string.
    #!/usr/bin/perl use strict; use warnings; my $c = 0; while (1) { $c ++; my $r = rand; die "Failed ($r) after $c attempts.\n" if substr ($r, 2) =~ /\D/; } __END__ Failed (1.13079331747201195e-05) after 17507 attempts.

    Abigail

      Thanks for the pointer. Simple fix:
      { my $r = substr rand, 2; sub crand() { length $r or ($r = rand) =~ tr/0-9//cd; chop $r; } } s[(.)]{$1 x (1+crand/3)}ge;
      On that note one could also
      # ... length $r or ($r = rand) =~ tr/3-9//cd; # ... s[(.)]{$1 x crand/3}ge;
      and even move the division up into crand although that's not a generic "cached rand" anymore.

      Makeshifts last the longest.

        Well, if you initialize $r as substr rand, 2, you haven't solved the problem - $r can still contain non digits.
        On that note one could also
        # ... length $r or ($r = rand) =~ tr/3-9//cd; # ...
        No, not really. What happens if rand returns a value whose stringification only contains 0, 1 and 2? $r will be empty.

        Besides, why are you caching the result of rand? Are you running out of random numbers? The overhead of a call to a user function (crand) is much higher than the overhead of a call to Perl primitive.

        Abigail