生成随机数,直到生成每个数字 [0, 9]
Generate random numbers until every digit [0, 9] is generated
我想做一个实验,我创建了一个列表,其中包含许多随机生成的序列列表,这些序列都包含 0 到 9 的每个数字(含),也就是说,生成函数是生成随机数并将它们放在一个列表中整数,而至少有 1 位数字未在列表中找到。
该实验的目的是尝试对诸如此类函数中预期的数字位数、序列可以得到多长时间(我的程序可以无限循环并且永远找不到最后一位数字吗?)等事情进行一些概括。 ,以及其他有趣的事情(对我来说)。
我正在使用 PERL 进行实验。
这个想法一开始看起来很简单,我坐下来,创建了一个列表,然后想我可以做一个循环运行任意次数(我决定选择 100 次),它调用一个函数 generate_sequence(输入:none,输出:每个数字至少包含 1 的数字列表)并将其添加到列表中。
我很快意识到,我很难从务实的角度清楚地说明生成包含每个数字之一的数字列表的含义。
我最初的尝试是制作一个数字列表 (0..9),当我生成数字时,我会在列表中搜索该数字(如果它在列表中)并将其删除。这样,它将生成数字,直到数字列表 "still needed" 为空。这种方法似乎没有吸引力,并且可能涉及很多冗余任务,例如每次生成数字时检查生成的数字是否在所需的数字列表中...
这样的问题有没有更优雅的解决方案?我对我处理函数的方式非常不满意。
一般来说,我需要一个什么都不接受的函数F,以及returns一个包含每个数字1..9的随机生成的数字列表,也就是说,它会立即停止因为生成了从 1 到 9 的每个数字。
提前致谢。
这应该有效 (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))
嗯,问题是如果您 'roll randomly' 您实际上并不知道需要多少次迭代 - 理论上它可能是无限的。
如果您在 perl
中这样做,您可能最好使用 List::Util
模块和 shuffle
- 向它提供您想要随机播放的元素列表。
例如
#!/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
的核心时,为什么还要麻烦呢?
然而,这听起来确实像是您在尝试生成一个列表,可能 包含重复项,直到您遇到终止条件。
我不完全确定为什么,但最好使用散列并计算出现次数。 (并在 'keys' 完成时终止)。
例如:
#!/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;
注意 - 由于 'random' 的性质,实际上滚动极长序列的可能性非常小 - 这意味着理论上你可能有很长 'streak' 不滚动6.
对于 %seen
中的奖励积分,您有一个生成数字的频率分布。
一个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
此方法计算填充数字字典所需的迭代次数:
import random
c = 0
d = dict()
while len(d.keys()) <10:
d[random.randint(0,9)] = 1
c += 1
print c
在您切换到 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
这是一个可能的 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)
在 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=>
在 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)
我想做一个实验,我创建了一个列表,其中包含许多随机生成的序列列表,这些序列都包含 0 到 9 的每个数字(含),也就是说,生成函数是生成随机数并将它们放在一个列表中整数,而至少有 1 位数字未在列表中找到。
该实验的目的是尝试对诸如此类函数中预期的数字位数、序列可以得到多长时间(我的程序可以无限循环并且永远找不到最后一位数字吗?)等事情进行一些概括。 ,以及其他有趣的事情(对我来说)。
我正在使用 PERL 进行实验。
这个想法一开始看起来很简单,我坐下来,创建了一个列表,然后想我可以做一个循环运行任意次数(我决定选择 100 次),它调用一个函数 generate_sequence(输入:none,输出:每个数字至少包含 1 的数字列表)并将其添加到列表中。
我很快意识到,我很难从务实的角度清楚地说明生成包含每个数字之一的数字列表的含义。
我最初的尝试是制作一个数字列表 (0..9),当我生成数字时,我会在列表中搜索该数字(如果它在列表中)并将其删除。这样,它将生成数字,直到数字列表 "still needed" 为空。这种方法似乎没有吸引力,并且可能涉及很多冗余任务,例如每次生成数字时检查生成的数字是否在所需的数字列表中...
这样的问题有没有更优雅的解决方案?我对我处理函数的方式非常不满意。
一般来说,我需要一个什么都不接受的函数F,以及returns一个包含每个数字1..9的随机生成的数字列表,也就是说,它会立即停止因为生成了从 1 到 9 的每个数字。
提前致谢。
这应该有效 (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))
嗯,问题是如果您 'roll randomly' 您实际上并不知道需要多少次迭代 - 理论上它可能是无限的。
如果您在 perl
中这样做,您可能最好使用 List::Util
模块和 shuffle
- 向它提供您想要随机播放的元素列表。
例如
#!/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
然而,这听起来确实像是您在尝试生成一个列表,可能 包含重复项,直到您遇到终止条件。
我不完全确定为什么,但最好使用散列并计算出现次数。 (并在 'keys' 完成时终止)。
例如:
#!/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;
注意 - 由于 'random' 的性质,实际上滚动极长序列的可能性非常小 - 这意味着理论上你可能有很长 'streak' 不滚动6.
对于 %seen
中的奖励积分,您有一个生成数字的频率分布。
一个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
此方法计算填充数字字典所需的迭代次数:
import random
c = 0
d = dict()
while len(d.keys()) <10:
d[random.randint(0,9)] = 1
c += 1
print c
在您切换到 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
这是一个可能的 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)
在 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=>
在 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)