How to generate an array with random values, without using a loop?

后端 未结 24 2098
逝去的感伤
逝去的感伤 2020-12-13 19:23

How can I generate an array in Perl with 100 random values, without using a loop?

I have to avoid all kind of loops, like \"for\", foreach\", while. This is my exerc

相关标签:
24条回答
  • 2020-12-13 20:03

    its ugly, but it works. the foreach is just to show that it does.

    #!/usr/bin/perl
    
    rand1();
    
    $idx = 1;
    
    foreach $item (@array) {
        print "$idx - $item\n";
        $idx++;
    }
    
    exit;
    
    
    
    sub rand1() {
        rand2();
        rand2();
        rand2();
        rand2();
    }
    
    sub rand2() {
        rand3();
        rand3();
        rand3();
        rand3();
        rand3();
    }
    
    sub rand3() {
        push @array, rand;
        push @array, rand;
        push @array, rand;
        push @array, rand;
        push @array, rand;
    }
    
    0 讨论(0)
  • 2020-12-13 20:03

    The question: do something (and something happens to be call rand()) a bunch of times without using a loop. Implied is, and without just repeating the source. None of the above answers actually answer this. They either repeat the source, or hide the looping. Here is a general approach that mitigates the repetition and does not hide looping (by implementing it using computed goto, or a regex, or recursion, etc). I call this approach "managed repetition."

    100 has four prime factors: 2*2*5*5 == 100. So we need two repetition managers, five and two:

    sub two{ my $y=shift; ($y->(), $y->()) }
    sub five{my $y=shift; ($y->(), $y->(), $y->(), $y->(), $y->()) } 
    

    then call them -- we're not recursing, because the recursion degenerate case constitutes a loop test -- just calling them:

    my @array = five(sub{five(sub{two(sub{two(sub{rand()})})})});
    

    There you are, a general way to call something a predetermined number of times without using a loop, rather, by delegating the repetition in an efficient and controlled way.

    Discussion question: which order should the fives and twos be in and why?

    0 讨论(0)
  • 2020-12-13 20:04
    # I rolled a die, honestly!
    my @random = (5, 2, 1, 3, 4, 3, 3, 4, 1, 6,
                  3, 2, 4, 2, 1, 1, 1, 1, 4, 1,
                  3, 6, 4, 6, 2, 6, 6, 1, 4, 5,
                  1, 1, 5, 6, 6, 5, 1, 4, 1, 2,
                  3, 1, 2, 2, 6, 6, 6, 5, 3, 3,
                  6, 3, 4, 3, 1, 2, 1, 2, 3, 3,
                  3, 4, 4, 1, 5, 5, 5, 1, 1, 5,
                  6, 3, 2, 2, 1, 1, 5, 2, 5, 3,
                  3, 3, 5, 5, 1, 6, 5, 6, 3, 2,
                  6, 3, 5, 6, 1, 4, 3, 5, 1, 2);
    
    0 讨论(0)
  • 2020-12-13 20:08

    Recursion:

    #!/usr/bin/perl
    use warnings; use strict;
    
    my @rands;
    my $i=1;
    
    sub push_rand {
        return if $#rands>=99;
        push @rands, rand;
        push_rand();
    }
    
    push_rand();
    
    for (@rands) { print "$i: $_\n"; $i++; }
    
    0 讨论(0)
  • 2020-12-13 20:09

    Someone asked for a pure regex solution. How about

    #!/usr/bin/perl
    open my $slf, $0;
    undef $/;
    (my $s = <$slf>) =~ s/./rand()." "/eggs;
    $s .= rand();
    
    0 讨论(0)
  • 2020-12-13 20:10

    For amusement value:

    A method that works on systems where EOL is a single character:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    $/ = \1;
    
    open 0;
    my @r = map rand,<0>;
    
    print "@r\n";
    

    A possibly nondeterministic method that does not use for, while, until:

    #!/usr/bin/perl
    use strict; use warnings;
    
    my @rand;
    
    NOTLOOP:
    push @rand, rand;
    sleep 1;
    goto NOTLOOP if 100 > time - $^T;
    
    print 0 + @rand, "\n";
    

    Using regular expressions:

    #!/usr/bin/perl
    use strict; use warnings;
    
    my $s = '-' x 100;
    $s =~ s/(-)/rand() . $1/eg;
    my @rand = $s=~ m/([^-]+)/g;
    

    Copying and pasting 100 rand invocations by hand is really passé:

    #!/usr/bin/perl
    use strict; use warnings;
    
    my $s = '(' . 'rand,' x 100 . ')';
    my @rand = eval $s;
    

    A file I/O based solution that does not require /dev/random:

    #!/usr/bin/perl
    use strict; use warnings;
    
    $/ = \1;
    
    my @rand;
    
    seek \*DATA, 0, 0;
    
    NOTLOOP:
    scalar <DATA>;
    push @rand, rand;
    goto NOTLOOP if $. < 100;
    __DATA__
    

    No reason to use recursion with Perl's goto

    #!/usr/bin/perl
    use strict; use warnings;
    use autodie;
    
    $/ = \1;
    
    open my $F, '<', \( 1 x 100 . 0 );
    
    my @rand or &notloop;
    
    sub notloop {
        my $t = <$F>;
        $t or return;
        push @rand, rand;
        goto \&notloop;
    }
    

    Here is a recursive string eval version:

    #!/usr/bin/perl
    use strict; use warnings; use autodie;
    
    local $/ = \1;
    open my $F, '<', \( 1 x 100 . 0 );
    
    my @rand;
    
    eval <<'NOLOOP'
    my $self = (caller(0))[6];
    <$F> or die;
    push @rand, rand;
    eval $self;
    NOLOOP
    ;
    

    Of course, all of these actually do contain loops, but they do not use the keywords you were barred from using.

    NB: This question has brought out the wacko in me, but I must admit it is amusing.

    0 讨论(0)
提交回复
热议问题