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
Generate the data:
my @array = map { rand() } (0..99);
Print the data to show that you have the right result:
print "$_\n" foreach (@array);
The generation loop is hidden (there's no looping keyword visible - just a function/operator).
While the copy'n'paste examples are novel and the map/foreach alternatives have also been mentioned, I think one approach that has not been discussed is recursion. Using recursion (an implicit loop) would need method calls and a simple 'if' statement: no for/grep/map/etc. It could be side-effecting or side-effect free.
Since this is homework, I will leave the implementation to the poster.
Happy coding.
BTW: Nobody has posted a regular expression solution yet ;-)
It's nice to see some even more innovative solutions! :-)
perl -E'say for&{sub{"\U\x{fb01}\x{fb03}"=~/.{0,2}.{0,3}.{0,3}.{0,4}+(?{$_[++$#_]=rand})(*FAIL)/||pop;@_}}'
/e
Regex SolutionThis:
($_=(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
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.
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 <stdlib.h>
#include <unistd.h>
#include <regex.h>
#include "perl.h"
#include "utf8.h"
#ifndef BROKEN_UNICODE_CHARCLASS_MAPPINGS
.{0,2}
.{0,3} .{0,3}
.{0,4}
#define rand() (random()<<UTF_ACCUMULATION_SHIFT^random()&UTF_CONTINUATION_MASK)
+(?{ $_ [++$#_] = rand() || rand() || UTF8_TWO_BYTE_LO (*PERL_UNICODE)
#else (*PRUNE)
#define FAIL (*ACCEPT)
}) (*FAIL)
#endif (*COMMIT)
)poop || pop @{ (*_{ARRAY}) }
;#; @{ (*SKIP:REGEX) }
@{ (*_{ARRAY}) }
}
}
The way to understand how the second regex solution works is:
\170
is "x".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. ☺
Nothing could be simpler!
my @rands = (rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand, rand, rand, rand, rand, rand, rand, rand, rand, rand,
rand, rand);
sub f {
my $n = shift;
if( $n == 0 ) {
return @_;
}
else {
return f( $n-1, rand, @_ );
}
}
my @random_array = f(100);
my @rand = map { rand } ( 1..100 );
But a map is just a loop with fancy window-dressing.
If you need to do something 100 times, you're going to need to use some kind of iterative structure.