这个工作得很好,但有时候数字从0开始:
import random
numbers = random.sample(range(10), 4)
print(''.join(map(str, numbers)))
我发现了很多例子,但没有一个能保证序列不会以0
开头。
答案 0 :(得分:65)
我们生成1 - 9范围内的第一个数字,然后从剩余数字中取出接下来的3个数字:
import random
# We create a set of digits: {0, 1, .... 9}
digits = set(range(10))
# We generate a random integer, 1 <= first <= 9
first = random.randint(1, 9)
# We remove it from our set, then take a sample of
# 3 distinct elements from the remaining values
last_3 = random.sample(digits - {first}, 3)
print(str(first) + ''.join(map(str, last_3)))
生成的数字是等概率的,我们只需一步即可获得有效数字。
答案 1 :(得分:31)
直到你喜欢的东西为止:
import random
numbers = [0]
while numbers[0] == 0:
numbers = random.sample(range(10), 4)
print(''.join(map(str, numbers)))
答案 2 :(得分:20)
这与其他答案非常相似,但您可以在1000-9999范围内绘制一个随机整数,而不是sample
或shuffle
,直到得到一个只包含唯一数字的整数:
import random
val = 0 # initial value - so the while loop is entered.
while len(set(str(val))) != 4: # check if it's duplicate free
val = random.randint(1000, 9999)
print(val)
正如@Claudio在评论中指出的那样,范围实际上只需要是1023 - 9876,因为该范围之外的值包含重复的数字。
通常random.randint
会比random.shuffle
或random.choice
快得多,所以即使更有可能需要多次绘制(如@karakfa所指出的),它最多可达3次比任何shuffle
,choice
方法更快,也需要join
个位数。
答案 3 :(得分:15)
我不太了解Python,但像
digits=[1,2,3,4,5,6,7,8,9] <- no zero
random.shuffle(digits)
first=digits[0] <- first digit, obviously will not be zero
digits[0]=0 <- used digit can not occur again, zero can
random.shuffle(digits)
lastthree=digits[0:3] <- last three digits, no repeats, can contain zero, thanks @Dubu
更有用的迭代,实际创建一个数字:
digits=[1,2,3,4,5,6,7,8,9] # no zero
random.shuffle(digits)
val=digits[0] # value so far, not zero for sure
digits[0]=0 # used digit can not occur again, zero becomes a valid pick
random.shuffle(digits)
for i in range(0,3):
val=val*10+digits[i] # update value with further digits
print(val)
从其他解决方案中窃取碎片后,再加上来自@DavidHammen的提示:
val=random.randint(1,9)
digits=[1,2,3,4,5,6,7,8,9]
digits[val-1]=0
for i in random.sample(digits,3):
val=val*10+i
print(val)
答案 4 :(得分:11)
拒绝抽样方法。从10位数创建一个4位数的随机组合,如果不符合标准,则重新取样。
r4=0
while r4 < 1000:
r4=int(''.join(map(str,random.sample(range(10),4))))
注意到这与@Austin Haskings的answer
基本相同答案 5 :(得分:11)
[固定]在一个位置上移动所有四位数字不对。固定位置的交换前导零也不对。但是,前导零与九个位置中的任何一个的随机交换是正确的,并给出相同的概率:
""" Solution: randomly shuffle all numbers. If 0 is on the 0th position,
randomly swap it with any of nine positions in the list.
Proof
Lets count probability for 0 to be in position 7. It is equal to probability 1/10
after shuffle, plus probability to be randomly swapped in the 7th position if
0 come to be on the 0th position: (1/10 * 1/9). In total: (1/10 + 1/10 * 1/9).
Lets count probability for 3 to be in position 7. It is equal to probability 1/10
after shuffle, minus probability to be randomly swapped in the 0th position (1/9)
if 0 come to be on the 0th position (1/10) and if 3 come to be on the 7th position
when 0 is on the 0th position (1/9). In total: (1/10 - 1/9 * 1/10 * 1/9).
Total probability of all numbers [0-9] in position 7 is:
9 * (1/10 - 1/9 * 1/10 * 1/9) + (1/10 + 1/10 * 1/9) = 1
Continue to prove in the same way that total probability is equal to
1 for all other positions.
End of proof. """
import random
l = [0,1,2,3,4,5,6,7,8,9]
random.shuffle(l)
if l[0] == 0:
pos = random.choice(range(1, len(l)))
l[0], l[pos] = l[pos], l[0]
print(''.join(map(str, l[0:4])))
答案 6 :(得分:6)
您可以使用3个数字的全范围,然后在剩余数字中选择前导数字:
import random
numbers = random.sample(range(0,10), 3)
first_number = random.choice(list(set(range(1,10))-set(numbers)))
print(''.join(map(str, [first_number]+numbers)))
如果需要重复选择(如果你对数字位数保持合理),另一种方法是使用itertools.permutations
预先计算可能输出的列表,过滤出具有前导的那些零,并从中构建一个整数列表:
import itertools,random
l = [int(''.join(map(str,x))) for x in itertools.permutations(range(10),4) if x[0]]
这是一些计算时间,但是之后你可以打电话:
random.choice(l)
你想要多少次。它非常快,并提供均匀分布的随机性。
答案 7 :(得分:4)
我不懂Python所以我会为这个特定的问题发布一个伪代码解决方案:
创建一个包含基于0的数字列表的查找变量:
lu = [1, 2, 3, 4, 5, 6, 7, 8, 9]
生成四个基于0的随机数,如下所示:
r1 = random number between 0 and 8
r2 = random number between 0 and 8
r3 = random number between 0 and 7
r4 = random number between 0 and 6
使用lookup变量将随机数逐个转换为数字。每次查找后,通过删除已使用的数字来改变查找变量:
d1 = lu[r1]
lu.remove(d1)
lu.insert(0)
d2 = lu[r2]
lu.remove(d2)
d3 = lu[r3]
lu.remove(d3)
d4 = lu[r4]
lu.remove(d4)
打印结果:
print concatenate(d1, d2, d3, d4)
可以稍微概括一下这个想法。例如,您可以创建一个接受列表(数字)和数字(所需结果长度)的函数;该函数将返回数字并通过删除用尽的数字来改变列表。以下是此解决方案的JavaScript实现:
function randomCombination(list, length) {
var i, rand, result = "";
for (i = 0; i < length; i++) {
rand = Math.floor(Math.random() * list.length);
result += list[rand];
list.splice(rand, 1);
}
return result;
}
function desiredNumber() {
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9],
result;
result = randomCombination(list, 1);
list.push(0);
result += randomCombination(list, 3);
return result;
}
var i;
for (i = 0; i < 10; i++) {
console.log(desiredNumber());
}
答案 8 :(得分:2)
以下是我的表现
while True:
n = random.randrange(1000, 10000)
if len(set(str(n))) == 4: # unique digits
return n
更一般地说,给定一个生成器,您可以使用内置函数filter
和next
来获取满足某些测试函数的第一个元素。
numbers = iter(lambda: random.randrange(1000, 10000), None) # infinite generator
test = lambda n: len(set(str(n))) == 4
return next(filter(test, numbers))
答案 9 :(得分:1)
next
Pythonic编写的方法是使用2个嵌套生成器和next
:
from random import randint
from itertools import count
print(next(i for i in (randint(1023, 9876) for _ in count()) if len(set(str(i))) == 4))
# 8756
它基本上是@MSeifert's answer
的单行变体如果你需要很多随机数,你可以投入一些时间和内存来预处理所有可接受的数字:
import random
possible_numbers = [i for i in range(1023, 9877) if len(set(str(i))) == 4]
1023
和9877
用作边界,因为低于1023或大于9876的int不能有4个唯一的,令人困惑的数字。
然后,您只需要random.choice
来快速生成:
print(random.choice(possible_numbers))
# 7234
答案 10 :(得分:0)
免责声明:这是一种可怕的反Python方法,严格用于基准测试部分(参见@ DavidHammen的评论和http://ideone.com/qyopLF) 我们的想法是在一个步骤中生成数字的序列号,然后修复任何冲突:
rnd=random.randint(0,4535)
(rnd,d1)=divmod(rnd,9)
(rnd,d2)=divmod(rnd,9)
#(rnd,d3)=divmod(rnd,8)
#(rnd,d4)=divmod(rnd,7)
(d4,d3)=divmod(rnd,8) # miracle found: 1 divmod happens to run faster than 2
现在我们有d1 = 0..8,d2 = 0..8,d3 = 0..7,d4 = 0..6,它可以通过运行rnd = 4535(4535 = 9)的片段进行测试*顺便提一下9 * 8 * 7-1)
首先,必须修补d1
d1=d1+1 # now d1 = 1..9
然后d2必须在必要时“跳过”d1
if d2>=d1
d2=d2+1 # now d2 = 0..9 "-" d1
然后必须用剩下的数字完成同样的事情,快速变得丑陋:
if d3>=d1:
d3=d3+1 # now d3 = 0..8 "-" d1
if d3>=d2:
d3=d3+1 # now d3 = 0..9 "-" {d1,d2}
elif d3>=d2: # this branch prepares for the other variant
d3=d3+1
if d3>=d1: # ">=" is preserved for consistency, here "==" may occur only
d3=d3+1
最后一部分是灾难性的:
if d4>=d1:
d4=d4+1
if d4>=d2:
d4=d4+1
if d4>=d3:
d4=d4+1
elif d4>=d3:
d4=d4+1
if d4>=d2:
d4=d4+1
elif d4>=d2:
d4=d4+1
if d4>=d1:
d4=d4+1
if d4>=d3:
d4=d4+1
elif d4>=d3:
d4=d4+1
if d4>=d1:
d4=d4+1
elif d4>=d3:
d4=d4+1
if d4>=d2:
d4=d4+1
if d4>=d1:
d4=d4+1
elif d4>=d1:
d4=d4+1
if d4>=d2:
d4=d4+1
对于更长的数字,使用位域可能会更快,但我看不到一个简单的方法。 (检查&gt; =一次关系是不够的,因为在进行增量后很容易发生碰撞。 例如d1 = 1,d2 = 2,d3 = 1:d3与d1发生碰撞,但最初不与d2发生碰撞。然而,在“打洞”1后,d3变为2,现在它与d2发生碰撞。事先没有发现这种碰撞的简单方法。
由于代码很糟糕,我在最后放了一个验证步骤
val = d1*1000 + d2*100 + d3*10 + d4
#if len(set(str(val))) != 4: print(str(val)+" "+str(o1)+","+str(o2)+","+str(o3)+","+str(o4))
if len(set(str(val))) != 4: print(val)
它已经比其他真正快速的代码更快(注释验证显示在divmod-s之后保留的原始数字,用于调试目的。这不是那种立即起作用的代码......)。评论这两个验证会使它更快。
编辑:关于检查这个和那个
这是一种方法,在最小有效输入组(0 ... 4535)和有效输出(9 * 9 * 8 * 7可能的4位数字,不同的数字,不是 - 之间保持1:1的关系 - 开始与 - 0)。因此,一个简单的循环可以而且应该生成所有数字,它们可以逐个检查,然后可以将它们收集到一个集合中,以便查看它们是否都是截然不同的结果
实际上:
collect=set()
for rnd in range(0,4536):
(rnd,d1)=divmod(rnd,9)
... rest of the code, also the verification step kept active ...
collect.add(val)
print(len(collect))
1)它不会在循环中打印任何内容(所有结果都是带有不同数字的4位数字)
2)最后将打印4536(所有结果都不同)
可以为第一个数字(d1)添加验证,此处我现在假设“(mod 9)+1”不会为0。
答案 11 :(得分:-6)
这将在第一个数字后允许零 -
numbers = random.sample(range(1,10),1) + random.sample(range(10),3)