Numpy数组项顺序 - 序列的平均分布

4
假设我有一个已经打乱的numpy数组:
a = np.array([1,2,3,4,5,6]*6)
np.random.shuffle(a)

如何确保洗牌后的数组中每个元素都与其他元素相同数量地相邻?
例如,我想要确保数字1在数组中跟随数字2的次数与其跟随数字4的次数相同。对于所有其他数字也是如此。
我们可以假设这个列表是循环的,即第一个项目跟随最后一个项目。
通常情况下,我会发布一些我尝试过的代码,但是对于这个问题,我感到无助。
我能想到的最低效的方法是编写一个函数来计算一个数字跟随另一个数字的次数,然后检查所有计数是否相等。如果不是,则重新洗牌。
但这并不能保证我最终会得到符合平均分布标准的列表。

你想要的在数学上是不可能的。你有36个数字,但只有35个“跟随者”。 - Diego Basch
这个需要最小的数组长度是多少?还是我们总会少一个? - Simon
1
第一个数字没有任何东西跟随,因此你少了一个数字。如果你将列表视为循环,则有可能。 - Diego Basch
有意义,为了这个问题的目的,我可以做出循环假设。 - Simon
使用排列运算符生成所有36种可能性?您是否需要它们仍然保持随机顺序?如果是这样,那么您将不得不编写“shuffle”函数;这不是内置功能。 - Prune
主要的限制条件是相等。确保相等后,我希望顺序尽可能随机,是的,假设这个问题有多于一个唯一解。 - Simon
1个回答

3

这是我能想到的最好的方法。注意,对于36个数字,每个数字必须恰好跟在其他数字后面一次。

while True:
    x = {i: set(range(1,7)) for i in range(1,7)}

    a = [random.choice(range(1,7))]  # start with a random number
    last = a[-1]
    while x[last]:
        next = random.choice(list(x[last]))
        x[last].remove(next)
        a.append(next)
        last = next

    if len(a) == 37:
        # We get to length 37 if and only if each set above is exhausted.
        # In this case, the first item will always equal the last item
        # (proof left as an exercise for the reader), so remove it.
        a = a[:-1]
        break

print(''.join(str(i) for i in a))

对我来说,它产生了221164425231355145433465615366263241,似乎符合标准。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接