关于perl:如何使用随机值生成数组,而不使用循环?

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

如何在不使用循环的情况下用Perl生成具有100个随机值的数组?

我必须避免所有的循环,比如"for","foreach",同时。这是我在实验室的练习。我找不到解决这个问题的方法,因为我是Perl的新手。

在C中,生成这个数组非常简单,但我不知道如何用Perl来实现。


娱乐价值:

一种在EOL为单个字符的系统上工作的方法:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/perl

use strict;
use warnings;

$/ = \1;

open 0;
my @r = map rand,<0>;

print"@r
"
;

号不使用forwhileuntil的一种可能不确定的方法:

1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/perl
use strict; use warnings;

my @rand;

NOTLOOP:
push @rand, rand;
sleep 1;
goto NOTLOOP if 100 > time - $^T;

print 0 + @rand,"
"
;

号使用正则表达式:

1
2
3
4
5
6
#!/usr/bin/perl
use strict; use warnings;

my $s = '-' x 100;
$s =~ s/(-)/rand() . $1/eg;
my @rand = $s=~ m/([^-]+)/g;

号手工复制粘贴100个rand调用实际上是通过的é;:

1
2
3
4
5
#!/usr/bin/perl
use strict; use warnings;

my $s = '(' . 'rand,' x 100 . ')';
my @rand = eval $s;

号一种基于文件I/O的解决方案,不需要/dev/random

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/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__

号没有理由对Perl的goto使用递归

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/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;
}

号这里是递归字符串eval版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/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
;

当然,所有这些实际上都包含循环,但它们不使用禁止使用的关键字。

NB:这个问题让我产生了怪癖,但我必须承认这很有趣。


再简单不过了!


纯regex溶液

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

/eregex溶液

这是:

1
2
3
4
($_=(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"@_
"
;

无环产生:

1
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

递归数值函数解

实际上,如果打印数组,会执行以下操作:

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

第二个解决方案现在可以很容易地获得不同数量的随机数,因为按照上面的分配,您可以做到以下几点:

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

是的,这确实是一个名为42()的函数。上一次对@_的赋值创建了它以及其他一百个以数字命名的函数。

解释

第一个regex解决方案依赖于unicode复杂的两个匹配字符的大小写。它可能(或不可能)更容易理解,加上空格和注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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})     }
    }
}

了解第二个regex解决方案如何工作的方法是:

  • 首先,将编译时常量表达式减少为更常用的形式,这样您就可以更容易地读取文本。例如,\170是"x"。
  • 第二,在每次替换中,将双e修剪为单e,然后两次打印出字符串中剩下的内容。

我相信你会感激你的评论的。:)

对于递归解决方案,添加空白可能会有所帮助:

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

需要将变量作为参数传递是由于需要lvalue的自动递减。我这样做是因为我不想说两次$_[0] - 1,也不想说任何命名的临时变量。这意味着你可以做到:

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

完成后,$N == 0,因为传递隐式引用语义。

对于一点重复的代价,您可以放宽左值参数的需要。

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

现在您不再需要左值参数,因此可以编写:

1
print for 100->(100);

得到100个随机数。当然,您也有100个其他的数值函数,因此您可以通过以下任何一种方式获得随机数列表:

1
2
3
4
5
6
7
8
9
10
@vi = 6->(6);
@vi = &6( 6);

$dozen = 12;

@dozen         =  $dozen->($dozen);
@baker's_dozen = &$dozen(++$dozen);

@_ = 100;
print &0;  # still a hundred of '
em

(对那些愚蠢的颜色感到抱歉。一定是个臭虫。)

我相信一切都会好起来的。?


1
my @rand = map { rand } ( 1..100 );

但一张地图只是一个装饰华丽的橱窗的环。

如果你需要做100次,你需要使用某种迭代结构。


1
2
3
4
5
6
7
8
9
10
11
# 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);


太糟糕了,大多数解决方案都集中在非循环部分,而忽略了随机数部分:

1
2
3
4
use LWP::Simple;

my @numbers = split /\s+/, #/ Stackoverflow syntax highlighting bug
    get( 'http://www.random.org/integers/?num=100&min=1&max=100&col=1&base=10&format=plain&rnd=new' );

这是汤姆等着看的疯狂,但我让它稍微疯狂一点。此解决方案将问题减少到:

1
my @numbers = rand( undef, 100 ); # fetch 100 numbers

普通随机数通常取0或1个参数。我给了它一个新的原型,它允许第二个参数记录返回多少个数字。

但请注意,与真实的rand有所不同。这不是连续的,所以可用的数字要少得多,并且包含在上界。另外,由于这一个采用了两个参数,因此它与期望实际参数的程序不兼容,因为这样的语句在每个参数中的解析方式不同:

1
 my @array = rand 5, 5;

但是,这里没有什么特别的关于CORE::GLOBAL::rand()。您不必更换内置的。你只是有点恶心而已。

我在里面留了一些print声明,这样你就可以看到它的工作了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
BEGIN {
    my @buffer;

    my $add_to_buffer = sub {
        my $fetch = shift;
        $fetch ||= 100;
        $fetch = 100 if $fetch < 100;
        require LWP::Simple;
        push @buffer, split /\s+/, #/ Stackoverflow syntax highlighting bug
          LWP::Simple::get(
           "http://www.random.org/integers/?num=$fetch&min=1&max=100&col=1&base=10&format=plain&rnd=new"
            );
        };

    my $many = sub ($) {
        print"Fetching $_[0] numbers
"
;
        $add_to_buffer->($_[0]) if @buffer < $_[0];
        my @fetched = splice @buffer, 0, $_[0], ();
        my $count = @fetched;
        print"Fetched [$count] @fetched
"
;
        @fetched
        };

    *CORE::GLOBAL::rand = sub (;$$) {
        my $max = $_[0] || 1; # even 0 is 1, just like in the real one
        my $fetch = $_[1] || ( wantarray ? 10 : 1 );
        my @fetched = map { $max * $_ / 100 } $many->( $fetch );
        wantarray ? @fetched : $fetched[-1];
        };
    }

my @rand = rand(undef, 5);
print"Numbers are @rand

"
;

@rand = rand(87);
print"Numbers are @rand

"
;

$rand = rand(undef, 4);
print"Numbers are $rand

"
;

$rand = rand();
print"Numbers are $rand

"
;

$rand = rand(undef, 200);
print"Numbers are $rand

"
;

不过,我的随机数来源对于这种技术并不重要。如果愿意,可以从/dev/random或/dev/urandom中读取以填充缓冲区。


1
2
3
4
5
6
7
8
9
10
11
sub f {
    my $n = shift;
    if( $n == 0 ) {
        return @_;
    }
    else {
        return f( $n-1, rand, @_ );
    }
}

my @random_array = f(100);


由于任务似乎是让您使用递归或者学习如何以一种不那么简单的形式编写一个简单的循环,所以我谦虚地提交了以下完全可执行的Perl程序:

Camel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#!/usr/bin/perl
                                      ''=~('('.'?'
           .'{'.(                   '`'|'%').("\["^
        '-').('`'|                '!').('`'|',').'"'
 .'\'.'$'.  ("\`"|              ',').('`'|')').('`'|
'-').'='.('^'^("\`"|            '/')).('^'^('`'|'.')).
('^'^('`'|'.')).';'.(          '!'^'+').('`'|'&').('`'
  |'/').('['^')').'('        .'\'.'$'.'='.'='.(('^')^(
       '`'|'/')).';'.      '\'.'$'.'='.'<'.'='.'\'.'$'
      .('`'|(',')).(     '`'|')').('`'|'-').';'.'+'."\+".
     '\'.'$'.('=').   ')'.'\'.'{'.('['^'+').('['^"\.").(
    '
['^'(').("\`"|   '(').('{'^'[').'\'.'@'.'='.','.("\{"^
    '
[').('['^')').  ('`'|'!').('`'|'.').('`'|'$').'\'.'}'.(
    '!'^'+').'\'.  '$'.'='.'='.('^'^('`
'|'/')).';'.('!'^'+')
    .('
`'|('&')).(  '`'|'/').('['^')').('{'^'[').'('.'\'.'@'.
    '
='.')'.('{'^'[').'\'.'{'.('!'^'+').('*'^'#').('['^'+').(
    '['^')').('`'|')').('`'|'.').('['^'/').('{'^'[').'\'.'"'.(
     '['^')').('`'|'!').('`'|'.').('`'|'$').('{'^'[').'\'.'$'.
     '='.('{'^'[').('`'|'/').('`'|'&').('{'^'[').'\'.'$'.("
\`"|
      ',').('`
'|')').('`'|'-').'='.'\'.'$'.'_'.'\'.'\'.(('`')|
       '
.').'\'.'"'.';'.('!'^'+').('*'^'#').'\'.'$'.'='.'+'.'+'
        .';'.('!'^'+').('*'^'#').'\'.'}'.'"
'.'}'.')');$:='.' ^((
         '
~'));$~='@'|'(';$^=')'^'[';$/='`'|'.';$,='('^"\}";  $\=
          '`
'|'!';$:=')'^'}';$~='*'|'`';$^='+'^'_'; $/="\&"|  '@'
            ;$,='['&'~';$\=','^'|';$:='.'^"\~";$~=  '@'|'('   ;$^
             =')'^ '[';$/='`
'|'.';$,='('^"\}";$\=   '`'|'!'   ;$:
                   =')'^'}';$~='*'|'`
';$^=('+')^    '_';$/=   '&'
                   |'
@';$,=    '['&'~';$\ ="\,"^     '|';$:   =(
                   ('
.'))^    "\~";$~=   ('@')|     '(';$^  =(
                   ('
)'))^    "\[";$/=  "\`"|      "\.";  (
                   ($,))=      '
('^'}';   ($\)         ='`'
                   |"\!";     $:=(')')^   '}';         ($~)
                    ='*'|    "\`";$^=    '+'^         '_';
                    ($/)=     '&'|'@'     ;$,=         '['&
                    '~';     $\=','       ^'|'         ;$:=
                    '.'^     '~'          ;$~=         '@'|
                    '(';      $^=         ')'          ^((
                    '['        ));       $/=           '`
'
                    |((         '
.'     ));            $,=
                    '
('          ^((   '}'              ))
                    ;(             ($\))=               ((
                    ((              '
`'))               ))
                    |+            "\!";$:=             ((
                   ')'            ))^+"\}";            $~
                  =((           '*'))|  '`
';           $^=
                 '
+'^        "\_";$/=   '&'          |'@'
               ;($,)=                                ('
[')&
            "\~";$\=                               '
,'^'|'

马提尼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
#!/usr/bin/perl
                                                  ''=~('(?{'.
                                                  ('`'|'%').(
                                                  '['^"\-").(
                                                  '`'|"\!").(
                                                  '`'|(',')).
                                                  '"\\$'.('`'
                                                    |',').(
                                                    '`'|')'
                                                    ).('`'|
                                                    ('-')).
                                                    ('=').(
                                                   '^'^('`'|
                                                   ('/'))).(
                                                   '^'^('`'|
                                                   ('.'))).(
                                                  '^'^(('`')|
                                                  '.')).';'.(
                                                 '!'^'+').('`'
                                                 |'&').(('`')|
                                                '/').('['^')').
                                                '(\\$=='.('^'^(
                                               '`'|'/')).';\\$='
                                              .'<=\\$'.('`'|',').
                                             ('`'|')').('`'|"\-").
                                            ';++\\$=)\\{'.('['^'+')
                                           .('['^'.').('['^'(').('`'
                                          |'(').('{'^'[').'\\@'.('`'|
                                          '!').('['^')').('['^"\)").(
                                          '`'|'!').('['^'"').','.('{'
                                          ^'[').('['^')').('`'|'!').(
                                          '`'|'.').('`'|"\$").'\\}'.(
'!'^'+').'\\$'.('`'|')').'='.("\^"^(      '`'|'/')).';'.('!'^('+')).(
 '`'|'&').('`'|'/').('['^')').('{'^       '[').'(\\@'.('`'|'!').('['^
   ')').('['^')').('`'|'!').('['^         '"').')'.('{'^"\[").'\\{'.(
    '!'^'+').('*'^'#').('['^'+')          .('['^')').('`'|')').("\`"|
      '.').('['^'/').('{'^'[')            .'\"'.('['^')').('`'|'!').
       ('`'|'.').('`'|"\$").(             '{'^'[').'\\$'.('`'|"\)").(
         '{'^'[').('`'|'/')               .('`'|'&').('{'^'[').'\\$'.
          ('`'|',').("\`"|                ')').('`'|'-').'=\\$_\\\'.
            ('
`'|('.')).                  '\";'.('!'^'+').('*'^'#').
             '\\$'.('`
'                   |')').'++;'.('!'^'+').('*'^
              "\#").                     '
\\}"})');$:='.'^'~';$~='@'
                |'('                      ;$^=')'^'[';$/='`'|"
\.";$,=
                '('^                      '}';$\='`'|'!';$:=')'^"
\}";
                ($~)                      ='*'|'`';$^='+'^'_';$/='&'|
                '@';                      $,='['&'~';$\=','^('|');$:=
                '.'^                      '~';$~='@'|'(';$^=')'^"
\[";
                ($/)                      ='`'|'.';$,='('^'}';$\='`'|
                '!';                      $:=')'^'}';$~='*'|('`');$^=
                '+'^                      '_';$/='&'|'@';$,='['&"
\~";
                ($\)                      =','^'|';$:='.'^'~';$~='@'|
                '(';                      $^=')'^'[';$/='`'|('.');$,=
                '('^                      '}';$\='`'|'!';$:=')'^"
\}";
                ($~)                      ='*'|'`';$^='+'^'_';$/='&'|
'@';$,='['&'~';$\=','^'|';$:='.'^'~'      ;$~='@'|'(';$^=')'^"
\[";$/=
'`'|'.';$,='('^'}';$\='`'|'!';$:=')'      ^'}';$~='*'|'`';$^='+'^'_';

。对于假日,雪花的内部是递归而不是迭代:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
#!/usr/bin/perl
           '?'                          =~(
         '('.'?'                      ."\{".(
        '`'   |'%'  ).('['^"\-").(  '`'|   '!'
         ).('`'|',').    '"'.    '\'.('$').(
         '`'|(',')).(    '`'|    ')').(('`')|
        ((  '-')   )).    +(    '`'   |')'  ).
       (((    '['   ))^+  ((  '/')   )).    '='
      .('^'^   ('`'|'/')) .( '^'^("\`"|   '.')).
     +(     '^'^('`'|'.')).';'.('!'^"\+").     ((
 '\')).'$'.('`'|'#').('`'|'/').('['^'.').('`'|'.').(
'['^  '/').'='.  (('^')^(    '`'|'/')  ).(';').(  '!'^
'+'    ).('['^    '(').(      ('[')^   "\.").(    '`'
|'"'  ).(('{')^  ('[')).(    '['^'+')  .('['^'.'  ).+(
 '['^'(').('`'|'(').'_'.('['^')').('`'|'!').('`'|'.')
     .(     '`'|'$').('{'^'[').'\'."\{".(     ((
      '
!'))^   '+').('{'^ (( ('[')))).(   ('{')^
       '
['    ).(   '{'^  ((  '[')   )).    (((
        ((  '
{')   )))    ^+    '['   ).+(  ((
         '
['))^')').(    '`'|    '%').(('[')^
         '/').(('[')^    '.')    .('['^')').(
        '`
'   |'.'  ).('{'^"\[").(  '`'|   ')'
         ).('`
'|                     "\&").(
           '
{'                          ^((
           '
['                          )))
         .'
\'.+                      '$'.'#'
        .+(   '`'|  '!').('['^')')  .''.   (((
         '['))^')').(    '`'|    '!').(('[')^
         '"').('_').(    '`'|    '/').(('`')|
        ((  '&')   )).    ((    '_'   )).(  ((
       '['    ))^   ')')  .(  '`'|   '!'    ).(
      ('`')|   '.').('`'| (( ('$')))).(   ('[')^
     ((     '('))).'>'.'\'.'$'.('`'|',').     +(
 '`'|')').('`'|'-').('`'|')').('['^'/').';'.('!'^'+')
.''.  ('{'^'[')  .(('{')^    ('[')).(  '{'^'[').  ('{'
^((    '['))).    ("\["^      '+').(    '['^'.'    ).(
'['^  '(').('`'  |"\(").(    '{'^'[')  .'\'.'@'  .''.
 ('
`'|'!').('['^')').('['^')').('`'|'!').('['^('"')).
     ((     '_')).('`'|'/').('`'|'&').'_'.     +(
      ('[')^   ')').('`'| (( ('!')))).(   ('`')|
       '.'    ).(   '`'|  ((  '$')   )).    (((
        ((  '[')   )))    ^+    '('   ).((  ((
         ',')))).('{'    ^'['    ).('['^')').
         ('`'|"
\!").(    '`'|    '.').(('`')|
        '$'   ).((  ';')).('!'^'+'  ).+(   '{'
         ^'[').(                      '{'^'['
           ).(                          '{'
           ^((                          '['
         ))).''.                      (('{')^
        '['   ).+(  '['^'+').('['^  '.')   .+(
         '['^('(')).(    '`'|    '(').('_').(
         '['^(')')).(    '`'|    '!').(('`')|
        ((  '.')   )).    +(    '`'   |'$'  ).
       '('    .((   ')')  ).  ';'.   (((    '!'
      ))^'+'   ).'\'.'}' .( '!'^'+').(   ('!')^
     ((     '+'))).('!'^'+').('['^('(')).(     ((
 '['))^'.').('`'|'"
').('{'^'[').('['^'+').('['^')').(
'
`'|  ')').('`'  |"\.").(    '['^'/')  .'_'.('['  ^')'
).(    '
`'|'%'    ).('`'      |'#').    (('[')^    '.'
).+(  '['^')').  ('['^'('    ).("\`"|  ')').('['  ^'-'
 ).('`'|'%').('{'^'[').'\'.'{'.('!'^'+').('{'^'[').(
     ((     '
{'))^'[').('{'^'[').('{'^'[')     .+
      '
\'.+   '$'.("\["^ (( '/'))).'='   .('['^
       '+'    ).(   '`'|  ((  '/')   )).    (((
        ((  '[')   )))    ^+    '+'   ).+(  ((
         '{'))^"\[").    '\'    .'@'.'_'.';'
         .('
!'^'+').(    '*'^    '#').(('[')^
        '+'   ).+(  '['^')').('`'|  ')')   .+(
         '`'|'.'                      ).('['^
           '/'                          ).(
           '{'                          ^((
         '['))).                      ('\').
        '
"'   .''.  ('['^')').('`'  |'!'   ).(
         '`'|('.')).(    '`'|    '$').(('{')^
         '[').('\').    '$'.    ('`'|"
\#").(
        ((  '`')   )|+    ((    '/'   ))).  +(
       '['    ^((   '.')  ))  .''.   (((    '`'
      ))|'.'   ).('['^'/' ). ('{'^'[').   ("\`"|
     ((     '/'))).('`'|'&').('{'^'[').''.     ((
 '\')).'$'.('`'|',').('`'|')').('`'|'-').('`'|')').(
'['^  '/').'='.  '\'.'$'    .(('[')^  '/').'\'  .''.
(((    '
\')))    .('`'|     "\.").    ('\').    '"'
.';'  .('!'^'+'  ).("\*"^    '#').''.  '\'.'$'.  ('`
'
 |'
#').('`'|'/').('['^'.').('`'|'.').('['^'/').('+').
     ((     '+')).';'.('!'^'+').('*'^'#').     +(
      ('[')^   '+').('['^ (( (')')))).(   ('`')|
       ')'    ).(   '`'|  ((  '.')   )).    (((
        ((  '[')   )))    ^+    '/'   ).((  ((
         '_')))).('['    ^')'    ).('`'|'%').
         ('`'|"\#").(    '['^    '.').(('[')^
        ')'   ).+(  '['^'(').('`'|  ')')   .+(
         '['^'-'                      ).('`'|
           '%'                          ).+
           '('                          .((
         '\')).                      '@'.'_'
        .((   '
)')  ).('{'^"\[").(  '`'|   ')'
         ).('`
'|'&').    ('{'    ^'[').('(').
         '
\'.'@'.'_'    .')'    .';'.(('!')^
        ((  '
+')   )).    ((    (((   '\'  ))
       )))    .((   '
}')  ).  ('!'   ^((    '+'
      ))).+(   '
!'^'+').( (( '['))^'+')   .('['^
     ((     '
.'))).('['^'(').('`'|'(').'_'     .(
 '['^')').('`
'|'!').('`'|'.').('`'|'$').'('.')'.';'.(
'['^  '+').('['  ^"\)").(    '`'|')')  .('`'|'.'  ).+(
'['    ^"\/").   "\_".(      ('[')^   "\)").(    '`'
|'%'  ).(('`')|  ('#')).(    '['^'.')  .('['^')'  ).+(
 '['^'(').('`'|')').('['^'-').('`'|'%').'('.'\'.'@'.
     +(     '
`'|'!').('['^')').('['^')').(     ((
      '`
'))|   '!').('['^ (( '"'))).'_'   .('`'|
       '/'    ).(   '`'|  ((  '&')   )).    '_'
        .(  '['^   ')'    ).    (((   '`')  )|
         '!').(('`')|    '.')    .('`'|'$').(
         '['^'(').')'    .';'    .'"
'.'}'.')'
        );(   $:)=  '
.'^'~';$~='@'  |'('   ;$^
         =('
)')^                      '[';#;#
           ;#;                          #;#

在每种情况下,输出都是这样的:

1
2
3
4
rand 1 of 100=0.625268682212667
rand 2 of 100=0.30160434879096
...
rand 100 of 100=0.584811321826528

如果希望看到嵌入在其中的循环或递归,可以使用perl -MO=Deparse martini.plperl -MO=Deparse camel.pl等。

只有Perl,对吗????

如果你想创造这些可爱的东西——看看Acme::Eyedrops


这里使用map作为单个值的局部化器,免除其循环状态:

1
my @rand = map&$_($_),sub{@_<=100&&goto&{push@_,rand;$_[0]};shift;@_};

或有两个接头:

1
my @rand = sub{&{$_[0]}}->(sub{@_<=100&&goto&{(@_=(rand,@_))[-1]};pop;@_});

这两个都是y-combinator风格的自传递子类,它们通过迭代构建列表,但其中一个显然比另一个更快。

你可以用s'g[^}]+'goto&{unshift@_,rand;$_[-1]'来解决效率低下的问题,但之后会变得有点长。

或者回避调用堆栈:

1
my @rand = do{local*_=sub{(push@_,rand)<100?goto&_:@_};&_};

或使用eval,无变量分配,无外部状态,一个anon sub:

1
my @rand = eval'sub{@_<100?eval((caller 1)[6]):@_}->(@_,rand)';

但最简洁的是:

1
my @rand = map&$_,sub{(100^push@_,rand)?goto&$_:@_};


尽管复制粘贴示例是新颖的,并且还提到了map/foreach替代方案,但我认为一种尚未讨论的方法是递归。使用递归(隐式循环)需要方法调用和简单的"if"语句:no for/grep/map/etc。它可能是副作用或无副作用的。

因为这是作业,所以我将把实现留给海报。

快乐的编码。

btw:nobody has posted a regular expression solution yet;-)

很高兴看到一些更具创新性的解决方案!-)


使用匿名子级和递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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,"
"
;

对于所有Fortran风扇,使用计算goto:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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),"
"
;


1
2
3
4
5
6
7
8
9
10
#!/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;


无Perl循环:

1
2
3
4
5
6
7
#!/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\\\
",rand()); return 0; }'
| gcc -x c - && ./a.out |!;
chomp(my @array=<>);


有人要一个纯的regex解决方案。怎么样

1
2
3
4
5
#!/usr/bin/perl
open my $slf, $0;
undef $/;
(my $s = <$slf>) =~ s/./rand().""/eggs;
$s .= rand();


另一个愚蠢的方法是,使用返回随机值的绑定数组如何?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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";

当然,绑定数组可以缓存这些值,这样就不需要第二个数组来拥有稳定的值。


1
2
3
    push @array, rand;
    push @array, rand;
    # ... repeat 98 more times


递归:

1
2
3
4
5
6
7
8
9
10
sub fill_rand {
 my ($array, $count) = @_;
   if ($count >= 1) {
   unshift @$array, rand();
   fill_rand ($array, --$count);
 }
}

my @array;
fill_rand (\@array, 100);

"尾叫优化"版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
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:

1
2
my @array;
eval("\@array = (" . ("rand()," x 100) .");");

如果您假设我的Perl是随机的(不是无根据的假设),那么可以使用Perl文件本身作为随机数据源:

1
2
3
4
5
6
open FILE, __FILE__ or die"Can't open" . __FILE__ ."
"
;
my $string;
read FILE, $string, 100;
close FILE;
my @array = map { ord } split //, $string;

当然,每次都会得到相同的结果,但这对于测试很有用。


它很难看,但它起作用。前臂只是为了表明它确实存在。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/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;
}


1
2
3
4
5
6
7
8
9
my $u;

open(URAND,"/dev/urandom") || die $!;

read(URAND, $u, 100);

close URAND;

my @array = split(/ */, $u);


1
@foo = (rand(), rand(), rand(), ... rand());


生成数据:

1
my @array = map { rand() } (0..99);

打印数据以显示您有正确的结果:

1
2
print"$_
"
foreach (@array);

生成循环是隐藏的(没有可见的循环关键字-只有一个函数/运算符)。


递归:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/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++; }


根据侦听器的请求,非纯regex解决方案:

1
2
3
$s="D" x 100;
$s=~s/D/rand().""/ge;
@s=split(/ /,$s);


问题是:在不使用循环的情况下做一些事情(有些事情恰好称为rand())。暗示是,而不只是重复来源。以上答案都不能回答这个问题。它们或者重复源代码,或者隐藏循环。这里有一种通用的方法,可以减少重复,并且不会隐藏循环(通过使用计算goto、regex或递归等实现循环)。我称这种方法为"有管理的重复"。

100有四个基本因子:2*2*5*5==100。所以我们需要两个重复管理器,五个和两个:

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

然后调用它们——我们不是递归的,因为递归退化的情况构成了一个循环测试——只是调用它们:

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

在这里,你可以用一种通用的方法,不使用循环,而是通过一种有效且可控的方式委托重复来调用预定的次数。

讨论问题:五人和二人应该按什么顺序排列?为什么?