Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何生成不以0开头且具有唯一数字的随机4位数?_Python_Python 3.x_Random_Sampling - Fatal编程技术网

Python 如何生成不以0开头且具有唯一数字的随机4位数?

Python 如何生成不以0开头且具有唯一数字的随机4位数?,python,python-3.x,random,sampling,Python,Python 3.x,Random,Sampling,这几乎可以正常工作,但数字有时以0开头: import random numbers = random.sample(range(10), 4) print(''.join(map(str, numbers))) 我已经找到了很多例子,但没有一个能保证序列不会以0开始。您可以对3个数字使用全范围,然后从剩余的数字中选择前导数字: import random numbers = random.sample(range(0,10), 3) first_number = random.choice(

这几乎可以正常工作,但数字有时以0开头:

import random
numbers = random.sample(range(10), 4)
print(''.join(map(str, numbers)))

我已经找到了很多例子,但没有一个能保证序列不会以
0

开始。您可以对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)

你想要多少次都行。它的速度非常快,并且提供了一个均匀分布的随机数。

这将允许在第一个数字后面加零-

numbers = random.sample(range(1,10),1) + random.sample(range(10),3)

只需循环,直到你有你喜欢的东西:

import random

numbers = [0]
while numbers[0] == 0:
    numbers = random.sample(range(10), 4)

print(''.join(map(str, numbers)))

拒绝抽样法。从10位数字中创建一个4位随机组合,如果不符合标准,则重新采样

r4=0    
while r4 < 1000:
    r4=int(''.join(map(str,random.sample(range(10),4))))
r4=0
r4<1000时:
r4=int(“”.join(map(str,random.sample(范围(10),4)))

注意,这基本上与@Austin Haskings的

相同,我们生成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)))
随机导入
#我们创建一组数字:{0,1,….9}
数字=设置(范围(10))

#我们生成一个随机整数,1这与其他答案非常相似,但您可以绘制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所指出的),它也比任何
shuffle
快3倍,
选择
也需要将单个数字连接起来的方法。

[Fixed]将所有四个数字移到一个位置是不正确的。将前导零与固定位置交换也不正确。但将前导零与九个位置中的任何一个进行随机交换是正确的,并且给出了相同的概率:

""" 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])))

我对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
从其他解决方案中窃取碎片后,再加上@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)

我不懂Python,因此我将针对这个特定问题发布一个伪代码ish解决方案:

  • 创建包含基于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实现:

函数随机组合(列表,长度){
var i,兰德,结果=”;
对于(i=0;i
以下是我的做法

while True:
    n = random.randrange(1000, 10000)
    if len(set(str(n))) == 4: # unique digits
        return n
更一般地说,给定一个生成器,您可以使用内置函数并获取满足某些测试函数的第一个元素

numbers = iter(lambda: random.randrange(1000, 10000), None) # infinite generator
test = lambda n: len(set(str(n))) == 4
return next(filter(test, numbers))
将生成器与
next
python式的编写方法是使用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
它基本上是一个单行程序的变体

预处理所有可接受的数字 如果您需要许多随机数,您可以投入一些时间和内存来预处理所有可接受的数字:

import random    
possible_numbers = [i for i in range(1023, 9877) if len(set(str(i))) == 4]
1023
9877
用作边界,因为小于1023或大于9876的整数不能有4个唯一的距离数字

然后,你只需要非常快的一代人:

print(random.choice(possible_numbers))
# 7234

免责声明:严格来说,这是一种可怕的反Python方法,用于基准测试部分(参见@DavidHammen的评论,和) 其思想是一步生成数字序列号,然后修复任何冲突:

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+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
对于较长的数字,使用位域可能会更快,但我看不到一种简单的方法。 (仅检查>=关系一次是不够的,因为在执行增量后很容易发生冲突。 e、 g.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之后保留的原始数字,用于调试目的。这不是一种可以立即工作的代码…)。对这两种验证进行评论会使其速度更快

编辑:关于checki
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)
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))