为了展示其中一些解决方案的作用,我发现多次运行蒙特卡罗算法并查看分布会有所帮助
首先是 @meta4 解决方案的整理版本,因为它是最充实的:
from random import randrange
def partial_shuffle(l, factor=5):
n = len(l)
for _ in range(factor):
a, b = randrange(n), randrange(n)
l[b], l[a] = l[a], l[b]
我们可以通过执行以下操作多次运行:
import numpy as np
n = 8
orig = list(range(n))
occur = np.zeros((n, n), int)
for _ in range(100000):
x = orig[:]
partial_shuffle(x,1)
occur[orig,x] += 1
如果我们以百分比的形式打印出现次数表,我们会得到:
[[33.5 9.6 9.5 9.4 9.4 9.6 9.5 9.5]
[ 9.6 33.2 9.7 9.5 9.6 9.6 9.4 9.4]
[ 9.5 9.6 33.2 9.5 9.6 9.5 9.6 9.5]
[ 9.5 9.3 9.6 33.4 9.5 9.5 9.5 9.6]
[ 9.4 9.6 9.4 9.6 33.3 9.5 9.7 9.5]
[ 9.6 9.5 9.6 9.6 9.4 33.3 9.5 9.6]
[ 9.4 9.7 9.5 9.5 9.5 9.6 33.2 9.7]
[ 9.5 9.5 9.6 9.5 9.7 9.5 9.6 33.2]]
每行代表该项目移动到该列的概率。在这种情况下(当n=8
)该算法倾向于将元素留在原来的位置,大约 33% 的时间,然后均匀地选取剩余部分
然后我可以运行 pjs 代码的(整理后的)版本:
from random import gauss
orderliness = 2
occur = np.zeros((n, n), int)
for _ in range(100000):
x = sorted(orig, key=lambda i: gauss(i * orderliness, 1))
occur[orig,x] += 1
这给出了非常不同的输出:
[[91.9 7.9 0.1 0. 0. 0. 0. 0. ]
[ 7.9 84.1 7.8 0.1 0. 0. 0. 0. ]
[ 0.1 7.8 84.1 7.9 0.1 0. 0. 0. ]
[ 0. 0.1 7.9 84.1 7.7 0.1 0. 0. ]
[ 0. 0. 0.1 7.7 84.2 7.8 0.1 0. ]
[ 0. 0. 0. 0.1 7.9 84.2 7.7 0.1]
[ 0. 0. 0. 0. 0.1 7.7 84.2 7.9]
[ 0. 0. 0. 0. 0. 0.1 7.9 91.9]]
即项目往往保持在接近它们开始的位置
这种表格非常适合检测分布中的偏差,而上面似乎没有证据表明这一点。但是,例如,使用 Artyom 的解决方案(shuffle(x, lambda: random() / 5)
) 给出以下结果:
[[ 0. 37.4 0. 0. 0. 16.7 23.8 22.1]
[ 0. 0. 100. 0. 0. 0. 0. 0. ]
[ 0. 0. 0. 100. 0. 0. 0. 0. ]
[ 0. 0. 0. 0. 100. 0. 0. 0. ]
[ 1.7 0. 0. 0. 0. 83.3 11.9 3. ]
[ 9. 7.4 0. 0. 0. 0. 64.2 19.4]
[ 26.7 17.9 0. 0. 0. 0. 0. 55.5]
[ 62.6 37.4 0. 0. 0. 0. 0. 0. ]]
这可能不是OP想要的。偏离对角线的高概率表示将数组旋转一个元素