如何使用随机值生成数组,而不使用循环?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用随机值生成数组,而不使用循环?相关的知识,希望对你有一定的参考价值。
如何使用100个随机值在Perl中生成数组,而不使用循环?
我必须避免所有类型的循环,例如“for”,foreach“,while。这是我的练习,来自我的实验室。我找不到解决方法,因为我是Perl的新手。
在C中,生成这个数组非常容易,但我不知道如何在Perl中实现它。
my @rand = map { rand } ( 1..100 );
但地图只是一个花式装饰的循环。
如果你需要做100次,你需要使用某种迭代结构。
虽然copy'n'paste示例是新颖的,并且还提到了map / foreach替代方案,但我认为尚未讨论的一种方法是recursion。使用递归(一个隐式循环)需要方法调用和一个简单的'if'语句:/ grep / map / etc。它可能是副作用或副作用。
由于这是家庭作业,我将把实施留给海报。
快乐的编码。
BTW:还没有人发布正则表达式解决方案;-)
很高兴看到一些更具创新性的解决方案! :-)
使用匿名子和递归:
use strict;
use warnings;
my @foo;
my $random;
($random = sub {
push @{$_[0]}, rand;
return if @{$_[0]} == $_[1];
goto &$random;
})->(@foo, 100);
print "@foo
";
print scalar @foo, "
";
使用计算goto,对所有fortran粉丝:
use strict;
use warnings;
sub randoms {
my $num = shift;
my $foo;
CARRYON:
push @$foo, rand;
# goto $#{$foo} < 99 ? 'CARRYON' : 'STOP';
goto ( ('CARRYON') x 99, 'STOP' )[$#$foo];
STOP:
return @$foo;
}
my @foo = randoms(100);
print "@foo
";
print scalar(@foo)."
";
2个匿名子和一个arrayref:
use strict;
use warnings;
my @bar = sub { return &{$_[0]} }->
(
sub {
push @{$_[1]}, rand;
goto &{$_[0]}
unless scalar(@{$_[1]}) == $_[2];
return @{$_[1]};
},
[],
100
);
print "@bar
";
print scalar(@bar), "
";
#!/usr/bin/perl
use strict;
use warnings;
my $x = 99;
my @rands = (rand,(*x=sub{rand,(map{*x->($x,sub{*x})}($x)x!!--$x)})->($x,*x));
use feature 'say';
say for @rands;
push @array, rand; push @array, rand; # ... repeat 98 more times
没有perl循环:
#!/usr/bin/perl
use strict;
use warnings;
@ARGV=q!echo 'int rand(void); int printf(const char *format, ...); int main(void) { int i; for(i=0;i<100;++i)printf("%d\\n",rand()); return 0; }' | gcc -x c - && ./a.out |!;
chomp(my @array=<>);
Someone要求一个纯正的正则表达式解决方案。怎么样
#!/usr/bin/perl
open my $slf, $0;
undef $/;
(my $s = <$slf>) =~ s/./rand()." "/eggs;
$s .= rand();
另一个愚蠢的方法,如何使用返回随机值的绑定数组?
use strict;
use warnings;
package Tie::RandArray;
use Tie::Array;
our @ISA = ('Tie::StdArray');
sub FETCH { rand; }
package main;
my @rand;
my $object = tie @rand, 'Tie::RandArray';
$#rand=100;
my @a= @somearray;
warn "@a";
当然,绑定的数组可以缓存值,因此不需要第二个数组来获得稳定的值。
递归:
sub fill_rand {
my ($array, $count) = @_;
if ($count >= 1) {
unshift @$array, rand();
fill_rand ($array, --$count);
}
}
my @array;
fill_rand (@array, 100);
“尾调优化”版本:
sub fill_rand {
my $array = shift;
my $count = shift;
unshift @$array, rand();
if ($count > 1) {
$count--;
@_ = ($array, $count);
goto &fill_rand;
}
}
my @array;
fill_rand(@array, 100);
使用eval:
my @array;
eval("@array = (" . ("rand(), " x 100) . ");");
如果你假设我的perl是随机的(不是无根据的假设),你可以使用perl文件本身作为随机数据的来源:
open FILE, __FILE__ or die "Can't open " . __FILE__ . "
";
my $string;
read FILE, $string, 100;
close FILE;
my @array = map { ord } split //, $string;
当然,每次都会得到相同的结果,但这对测试很有用。
它的丑陋,但它的工作原理。 foreach只是为了表明它确实如此。
#!/usr/bin/perl
rand1();
$idx = 1;
foreach $item (@array) {
print "$idx - $item
";
$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;
}
@foo = (rand(), rand(), rand(), ... rand());
为了娱乐价值:
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
";
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, "
";
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 ¬loop;
sub notloop {
my $t = <$F>;
$t or return;
push @rand, rand;
goto ¬loop;
}
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
;
当然,所有这些实际上都包含循环,但它们不使用您禁止使用的关键字。
注意:这个问题带来了我的怪话,但我必须承认它很有趣。
生成数据:
my @array = map { rand() } (0..99);
打印数据以显示您的结果正确:
print "$_
" foreach (@array);
生成循环是隐藏的(没有循环关键字可见 - 只是一个函数/运算符)。
my $u;
open(URAND, "/dev/urandom") || die $!;
read(URAND, $u, 100);
close URAND;
my @array = split(/ */, $u);
根据听众的请求,非纯正则表达式解决方案:
$s="D" x 100;
$s=~s/D/rand()." "/ge;
@s=split(/ /,$s);
递归:
#!/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: $_
"; $i++; }
问题是:在不使用循环的情况下做一些事情(有些事情恰好是调用rand()
)。隐含的是,而不仅仅重复源。上述答案都没有实际回答这个问题。它们要么重复源,要么隐藏循环。这是一种减轻重复并且不隐藏循环的一般方法(通过使用计算的goto,正则表达式或递归等实现它)。我把这种方法称为“管理重复”。
100有四个素因子:2 * 2 * 5 * 5 == 100.所以我们需要两个重复管理器,五个和两个:
sub two{ my $y=shift; ($y->(), $y->()) }
sub five{my $y=shift; ($y->(), $y->(), $y->(), $y->(), $y->()) }
然后调用它们 - 我
以上是关于如何使用随机值生成数组,而不使用循环?的主要内容,如果未能解决你的问题,请参考以下文章