这是我到目前为止的情况,但如果我超过前一个数字的正负11就会中断。因此,如果前一个数字为1,则下一个数字必须大于16.另外,我只想使用每个数字一次。
示例输出:
[3,45, 1, 16, 33, 3, 23.....]
到目前为止我的脚本是:
import random
new_array=[]
counter = 0
array=range(51)
array=array[1:51]
while len(new_array)<50:
y=random.choice(array)
if y not in new_array and counter!=0 and y not in (range(new_array[counter-1]-11,new_array[counter-1]+11)):
new_array.append(y)
counter+=1
elif counter == 0:
new_array.append(y)
counter+=1
else:
pass
答案 0 :(得分:1)
以下方法如何?从洗牌列表开始。对于每对,如果距离小于15,则旋转剩余的数字。
import random
def get_shuffled_list(length):
output = range(1, length+1)
i = 0
sanity = 0
while i < length and sanity == 0:
random.shuffle(output)
for i in range(1, length):
sanity = length - i + 1
while abs(output[i-1] - output[i]) <= 15 and sanity:
output.append(output[i])
del output[i]
sanity -= 1
if sanity == 0:
break
return output
print get_shuffled_list(50)
提供以下类型的输出:
[1, 38, 3, 33, 16, 43, 10, 41, 9, 35, 4, 50, 29, 8, 44, 28, 5, 32, 14, 40, 21, 47, 25, 48, 30, 12, 34, 18, 42, 15, 36, 13, 31, 2, 24, 7, 23, 39, 22, 6, 26, 49, 27, 11, 45, 19, 46, 17, 37, 20]
如果您没有任何符合条件的剩余数字,则会在最后出现问题,在这种情况下,请重新开始。对于10,000次洗牌的测试,我管理的最糟糕的情况是196次尝试。不理想,但确实有效。
答案 1 :(得分:0)
尝试这样的事情:
last
的初始值开头。
该值应为字符串('start'
)。 last == 'start'
。 abs(number - last)
小于15之前,请创建一个新的随机数。last
设置为列表的最后一个元素。 答案 2 :(得分:0)
编辑:没有回答这个问题,因为它可以并且会多次选择一些数字。留下它以防这个变种对其他人有用。
您使用的算法和JF建议的算法共享一个有趣的缺陷:它们所用的时间没有限制。如果你真的不走运,那么在宇宙结束之前函数就无法返回。
这是一个将在约束时间内执行的,即O(n)
:
import random
def spaced_randoms(min_val, max_val, number, space):
if max_val - min_val <= 2 * space:
raise ValueError('interval not large enough for space')
last = random.randint(min_val, max_val)
result = [last]
for _ in range(number - 1):
skip_low = max(0, min(space, last - min_val))
skip_high = max(0, min(space, max_val - last))
value = random.randint(min_val + skip_low, max_val - skip_high - 1)
last = value - skip_low if value < last else value + skip_high + 1
result.append(last)
return result
>>> print(spaced_randoms(0, 50, 50, 15))
[35, 10, 44, 26, 47, 22, 49, 29, 3, 28, 44, 17, 40, 3, 39, 7, 48, 22, 41, 5, 21, 4, 32, 9, 34, 3, 46, 3, 20, 38, 10, 49, 32, 16, 38, 5, 26, 45, 26, 49, 13, 44, 1, 30, 12, 30, 0, 46, 15, 42]
这个想法很简单:我们减少新数字的可能间隔以考虑禁用值。我们重新映射结果。例如,假设某个点last == 32
有15个空格,那么:
答案 3 :(得分:0)
嗯,沿着这条线的东西,用伪代码
sampled = []
n = 50
x = 15
curr = n + x + 1
for k in range(1, 1000):
# build exclusion range tuple, where you cannot sample,
# say for calc_ex_range(50, 15, 27) it should return
# (12, 42)
exclude_range = calc_ex_range(n, x, curr)
# build new sampling array, given the exclusion range
# result should be [1,2,3,4,5,6,7,8,9,10,11,43,44,45,46,47,48,49,50]
sampling_array = calc_sarray(n, exclude_range)
# remove already sampled numbers from sampling array
sampling_array = filter_sarray(sampling_array[:], sampled)
if len(sampling_array) == 0:
break
# sample one item from the array
curr = random.sample(sampling_array, 1)
sampled.append(curr)
复杂性将是O(N ^ 2),我猜,但它总是完成
更新
为了采样一次,过滤掉采样数组
答案 4 :(得分:0)
在另一个未能满足&#34的答案后,每个项目必须恰好出现一次&#34;要求,这里有一些想法:
如果我将间距称为两个连续数字之间的最小绝对差值,则:
不幸的是,我对算法理论不够好,无法建立正式的证据。而且,也许它只是我找不到更好的方法。但在这一点上,我没有看到任何方法,只能将最后一项作为图搜索进行选择。
然而,有趣的是,我无法承受更多时间。但如果你回来回答你自己的问题,我会喜欢阅读它。
答案 5 :(得分:0)
如果可以随意排除符合您标准的许多排列,您可以非常轻松地创建一个算法来生成可行的排列。
我能想到的最简单的例子如下:
{1,50}
划分为10个子范围,包含五个数字:{1,5},{6,10},{11,15}...
。{1,5},{21,25},{41,45},{11,15}...
3,22,41,15...
3,22,41,15...1,24,42,14...4,21...
您可以通过选择不同的子范围大小(例如15
或7
来对此进行简单的变体,尽管这会引入额外的复杂性,即不能均匀地划分原始范围)。或者,您可以按照永远不会使序列无效的规则随机转置输出序列的元素(或以其他方式改变序列)(即,您不能引入小于15的元素配对)。您还可以使子范围的排序为准随机,或者通过子范围更改ach迭代的排序。
即使有这些变化,这显然也不是任何可能的有效排列的完全随机选择。但在实践中,我预计这不太重要。
答案 6 :(得分:-1)
这个怎么样?我使用randint轻松获得所需范围内的整数:
import random
my_list = []
# This number should not be within 15 units from each
# new random integer:
previous = random.randint(1, 50)
# Loop until my_list' length is 50; see at the bottom
while True:
# Get a new random integer from 1 to 50
rand_int = random.randint(1, 50)
# If the new integer is NOT at a range within 15 of the previous number,
# append to the list; otherwise skip and try again
if not rand_int - 15 < previous < rand_int + 15:
my_list.append(rand_int)
# This new integer becomes the new previous
previous = rand_int
if len(my_list) >= 50:
# Break from the loop and print the new list
break
print(my_list)