生成随机数,直到生成每个数字[0,9]

时间:2015-10-21 19:27:09

标签: perl random scripting

我想做一个实验,我创建了许多随机生成序列列表的列表,这些列表都包含0到9的每个数字,也就是说,生成函数是生成随机数并将它们放在整数列表中虽然列表中找不到至少1位数字。

这个实验的目的是尝试对这样一个函数中预期的数字位数进行一些概括,一个序列可以获得多长时间(我的程序可以无限循环,永远不会找到最后一个数字?),以及其他有趣的事情(对我而言)。

我正在使用PERL进行实验。

这个想法起初看起来很简单,我坐下来,创建了一个列表,并认为我可以创建一个运行任意次数的循环(我决定选择100次),它调用一个函数generate_sequence(输入: none,output:包含每个数字中至少1个的数字列表)并将其添加到列表中。

我很快意识到我正在努力干净地指定实际意义,生成包含每个数字之一的数字列表。

我最初的尝试是创建一个数字列表(0..9),当我生成数字时,如果它在列表中,我会搜索该数字的列表,并将其删除。这样,它将生成数字,直到“仍然需要”的数字列表为空。这种方法似乎没有吸引力,可能涉及许多冗余任务,例如检查生成的数字是否在每次生成数字时所需的数字列表中...

对这样的问题有更优雅的解决方案吗?我对接近这个功能的方式非常不满意。

一般情况下,我需要一个不接受任何内容的函数F,并返回包含每个数字1..9的随机生成数字的列表,也就是说,只要从1到9(包括1和9)的每个数字,它就会停止生成。

提前致谢。

8 个答案:

答案 0 :(得分:5)

嗯,问题是如果你'随意滚动'你实际上并不知道你需要多少次迭代 - 理论上它可能是无限的。

如果您在perl中进行操作,那么使用List::Util模块和shuffle可能会好得多 - 请为其提供您想要随机播放的元素列表。

E.g。

#!/usr/bin/env perl

use strict; 
use warnings;

use List::Util qw( shuffle );

my @shuffled = shuffle ( 0..9 );

print @shuffled;

你可以很容易地重现这一点,但是为什么在List::Util是核心的时候为什么烦恼呢?5.7.3

然而,它确实听起来像您正在尝试生成列表,可能包含重复,直到您达到终止条件。

我不完全确定原因,但最好使用散列并计算出现次数。 (并在“钥匙”完成时终止。)

例如:

#!/usr/bin/env perl

use strict; 
use warnings;

my %seen;
my @list_of_numbers;

while ( keys %seen < 10 ) {
   my $gen = int rand ( 10 );
   $seen{$gen}++; 
   push ( @list_of_numbers, $gen );
}

print @list_of_numbers;

注意 - 由于“随机”的性质,实际上滚动极长序列的可能性非常小 - 这意味着理论上你可能有一个很长的'连胜'而不是滚动6。

对于%seen中的奖励积分,您的生成数字的频率差异。

答案 1 :(得分:1)

python实现:

from random import randint

s = set(range(10))
def f():
    result = []
    t = set()
    while 1:
        n = randint(0, 9)
        result.append(n)
        t.add(n)
        if t == s:
             return result

例如:

for i in range(10):
    print(len(f()))
   ....:     
20
34
69
22
23
25
20
29
30
32

答案 2 :(得分:0)

这应该有用(python):

import random
nums = []
while any([ i not in set(nums) for i in range(1,11)]):
    nums.append(random.randrange(1, 11, 1))

或更具体到你想要做的事情:

import random

lengths = []
for i in range(1000):
    nums = []
    while any([ i not in set(nums) for i in set(range(1,11))]):
        nums.append(random.randrange(1, 11, 1))
    lengths.append(len(nums))

答案 3 :(得分:0)

此方法计算填充数字字典所需的迭代次数:

import random

c = 0
d = dict()
while len(d.keys()) <10:
    d[random.randint(0,9)] = 1
    c += 1

print c

答案 4 :(得分:0)

在你切换到Perl之前写了这个...

from random import randrange

def F():
    todo = set(range(10))
    nums = []
    while todo:
        r = randrange(10)
        nums.append(r)
        todo.discard(r)
    return nums

>>> F()
[8, 2, 2, 3, 1, 0, 3, 9, 3, 4, 7, 4, 7, 5, 0, 9, 5, 5, 6]

另:

def F():
    done = 0
    nums = []
    while done < 1023:
        r = randrange(10)
        nums.append(r)
        done |= 1 << r
    return nums

答案 5 :(得分:0)

这是一个可能的Perl实现,它计算用10个数据库填充哈希值所需的迭代次数:

#!/usr/bin/perl

my $count = 0;
my %dict = ();

while (scalar keys %dict < 10) {
    $dict{int(rand(10))} = 1;
    $count ++;
}

print $count;

(见online demo

答案 6 :(得分:0)

在clojure中(尽管可能不是最优雅的):

(loop [n []
       s (set (range 0 10))]
  (if (= s (set n))
    n
    (recur (conj n (rand-int 10)) s)))

示例输出:

user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[0 6 2 8 5 2 0 0 9 3 0 3 0 1 7 5 0 4]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[2 1 7 7 3 2 8 8 4 7 5 0 1 3 0 3 0 4 0 0 3 7 3 4 5 8 1 3 8 5 3 5 5 9 4 0 2 1 2 7 8 3 9 7 8 6]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[7 1 8 3 1 1 0 6 8 4 9 7 0 0 2 7 4 0 1 1 8 8 4 3 9 8 4 2 8 3 2 8 4 6 0 9 9 7 2 3 0 3 0 4 2 4 0 5]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[9 1 9 0 9 5 3 0 3 8 4 0 1 6 3 0 1 8 0 3 8 3 5 4 3 9 8 8 8 8 2 2 8 9 9 3 9 2 5 1 1 3 4 6 3 1 4 0 2 6 7]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[4 1 5 5 5 5 2 2 5 5 3 1 5 3 5 1 4 2 4 2 3 1 4 7 1 9 3 8 0 8 4 0 9 3 4 9 9 1 8 8 0 6]
user=> (loop [n [] s (set (range 0 10))] (if (= s (set n)) n (recur (conj n (rand-int 10)) s)))
[0 4 0 9 1 8 4 8 6 6 6 9 8 4 9 0 9 3 3 7 6 1 4 3 8 1 1 4 9 5 1 4 1 2]
user=> 

答案 7 :(得分:0)

在Clojure中,我跟踪随机列表和现有值,从而避免在不断增长的列表中进行搜索。

    (defn random-list [ up-to ]
     (loop [ n [] tries [] ]
      (if (> (count n) (dec up-to))
        tries
        (let [i (rand-int up-to) n-tries (conj tries i)]
          (if (some #{i} n )
            (recur n n-tries)
            (recur (conj n i) n-tries))))))

我们可以定义类似的功能:

    (defn random-list-to-10 []
      (random-list 10))

    (random-list-to-10)
    ; [3 6 9 0 8 0 5 7 3 8 1 8 4 3 4 2]

我们也可以只采用几个随机元素:

    (take 5 (random-list 10))
    ; (6 1 0 9 5)