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

后端 未结 24 2134
逝去的感伤
逝去的感伤 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 19:58

    Pure Regex Solution

    perl -E'say for&{sub{"\U\x{fb01}\x{fb03}"=~/.{0,2}.{0,3}.{0,3}.{0,4}+(?{$_[++$#_]=rand})(*FAIL)/||pop;@_}}'
    

    Double‐/e Regex Solution

    This:

    ($_=(120.44.32)x(2+2*2**2)**2)=~s/\170/114.97.110.100/gee;
    s/(.*)/64.95.61.40.$1.41.35.89.65.78.69.84.85.84/ee;
    print "@_\n";
    

    looplessly produces this:

    0.636939813223766 0.349175195300148 0.692949079946754 0.230945990743699 0.61873698433654 0.940179094890468 0.435165707624346 0.721205126535175 0.0322560847184015 0.91310500801842 0.31596325316222 0.788125484008084 0.802964232426337 0.417745170032291 0.155032810595454 0.146835982654117 0.181850358582611 0.932543988687968 0.143043972615896 0.415793094159206 0.576503681784647 0.996621492832261 0.382576007897708 0.090130958455255 0.39637315568709 0.928066985272665 0.190092542303415 0.518855656633185 0.797714758118492 0.130660731025571 0.534763929837762 0.136503767441518 0.346381958112605 0.391661401050982 0.498108766062398 0.478789295276393 0.882380841033143 0.852353540653993 0.90519922056134 0.197466335156797 0.820753004050889 0.732284103461893 0.738124358455405 0.250301496672911 0.88874926709342 0.0647566487704268 0.733226696403218 0.186469206795884 0.837423290530243 0.578047704593843 0.776140208497122 0.375268613243982 0.0128391627800006 0.872438613450569 0.636808174464274 0.676851978312946 0.192308731231467 0.401619465269903 0.977516959116411 0.358315250197542 0.726835710856381 0.688046044314845 0.870742340556202 0.58832098735666 0.552752229159754 0.170767637182252 0.683588677743852 0.0603160539059857 0.892022266162105 0.10206962926371 0.728253338154527 0.800910562860132 0.628613236438159 0.742591620029089 0.602839705915397 0.00926448179027517 0.182584549347883 0.53561587562946 0.416667072500555 0.479173194613729 0.78711818598828 0.017823873107119 0.824805088282755 0.302367196288522 0.0677539595682397 0.509467036447674 0.906839536492864 0.804383046648944 0.716848992363769 0.450693083312729 0.786925293921154 0.078886787987166 0.417139859647296 0.9574382550514 0.581196777508975 0.75882630076142 0.391754631502298 0.370189654004974 0.80290625532508 0.38016959549288
    

    Recursive Numeric Function Solution

    As in fact, does this, if you print the array:

    @_=(*100=sub{$_[0]?(rand,(*{--$_[0]}=*{$_[0]})->(@_)):()})->($==100);
    

    The second solution now allows for getting different numbers of random numbers easily enough, since following the assignment above, you can do such niceties as:

     print for @42=42->($==42);
    

    And yes, that is indeed a function named 42(). The previous assignment to @_ created it along with a hundred other numerically named functions.


    Explanation

    The first regex solution relies on Unicode’s tricky casing of the two characters matched against. It may (or may not) be more easily understood with whitespace and comments added:

    use 5.010;
    
    say for &{
    
        sub  { "\U\x{fb01}\x{fb03}" =~ m((?mix-poop)
    
    #include 
    #include 
    #include 
    #include "perl.h"
    #include "utf8.h"
    
    #ifndef BROKEN_UNICODE_CHARCLASS_MAPPINGS
    
                            .{0,2}
    
                    .{0,3}          .{0,3}
    
                            .{0,4}
    
    #define rand() (random()<

    The way to understand how the second regex solution works is:

    • First, reduce the compile-time constant expressions into their more customary forms so you can more easily read the literals. For example, \170 is "x".
    • Second, trim down the double e to a single e in each substitution, then print out what that leaves in the string both times.

    I’m sure you’ll appreciate the comment. :)


    For the recursive solution, adding whitespace may help a little:

    (*100 = sub { $_[0]
                    ? ( rand, ( *{ --$_[0] } = *{ $_[0] } )->(@_) )
                    : ( )
                }
    )->( $= = 100 );
    

    The need to pass a variable as an argument is due to the auto-decrement requiring an lvalue. I did that because I didn’t want to have to say $_[0] - 1 twice, or have any named temporary variables. It means you can do this:

    $N = 100;
    print for $N->($N);
    

    And when you’re done, $N == 0, because of pass‐by‐implicit‐reference semantics.

    For the cost of a bit of repetition, you can relax the need of an lvalue argument.

    (*100 = sub { $_[0]
                     ? ( rand, ( *{ $_[0] - 1 } = *{ $_[0] } )->( $_[0] - 1 ) )
                     : ( )
                }
    )->( 100 );
    

    Now you no longer need an lvalue argument, so you can write:

    print for 100->(100);
    

    to get all 100 random numbers. Of course, you also have a hundred other numeric functions, too, so you can get lists of random numbers in any of these ways:

    @vi = 6->(6); 
    @vi = &6( 6);
    
    $dozen = 12;
    
    @dozen         =  $dozen->($dozen);
    @baker's_dozen = &$dozen(++$dozen);
    
    @_ = 100;
    print &0;  # still a hundred of 'em
    

    (Sorry ’bout the silly colors. Must be an SO bug.)

    I trust that clears everything up. ☺

提交回复
热议问题