我想为许多牧师制定一份时间表。条件是:
我不能随意使用(1到12),因为牧师有可能去同一个教堂(有机会他去同一个教堂的机率为8.3%)。
我想让他去同一个教会的机会很小(大约3%或更少)。
答案 0 :(得分:12)
你的条件并不要求随机选择下一个教会给定牧师。难道你不能遍历教会名单吗?
即,为每个牧师分配一个0-12的数字。为每个教会分配一个0-12的数字。第一个月:
第0个月:
牧师-0 - >教堂0
牧师-1 - >教堂1
牧师-2 - >教堂-2
...
pastor-n - >教堂-n
下个月,只需增加一个计数器(带环绕式)
第1个月:
牧师-0 - >教堂1
牧师-1 - >教堂-2
牧师-2 - >教堂3
...
pastor-n - >教堂-0
然后重复剩下的几个月:
第3个月:
牧师-0 - >教堂-2
牧师-1 - >教堂3
牧师-2 - >教堂4
...
牧师 - (n-1) - >教堂0
pastor-n - >教堂-1
所有这一切都有一个非常简单的循环(O(n))。如果它让你感到困惑,我建议用n = 3来试试纸上的循环。
如果要求随机性,请更新您的问题。
编辑PAX
我正在删除我的答案并对此进行投票,因为它是O(n)并且我的扩展以满足编辑的要求至少为O(n ^ 2)。
你仍然可以通过将pastor-0到pastor-N值索引变成一个随机排序的牧师数组来实现随机性,这样就可以使这个解决方案至少和我的一样好。
结束编辑PAX
答案 1 :(得分:1)
鉴于你有相同数量的牧师和教会,这是一个非常简单的算法:
每个教会的编号从0到12
构造一个包含0到12元素的数组。
在阵列上执行Knuth Shuffle(见下文),生成随机改组的教堂列表。
每位牧师都在他们自己的教会开始(如果牧师没有指定教会,只需对牧师0到12进行任意编号,并将他们与教会相同的数字进行匹配)。每个月,每位牧师都会搬到名单上的下一个教堂。如果他们在名单上的最后一个教堂,他们会去第一个。
这有一个很容易解释的好处:只需给每个牧师提供洗牌清单并告诉他们从哪里开始。
Knuth shuffle(大致)是:
def knuth_shuffle(l):
for i in range(len(l)):
j = random.randint(i, len(l))
l[i], l[j] = l[j], l[i]
非常重要的是要注意,在每次迭代中,您都要使用从已经选择 not 的那些中选择的随机元素交换列表中的当前项。这确保了可能的shuffle的数量与排列的数量完全匹配(因此,它们都具有相同的概率),基于交换随机元素的天真shuffle,或者将当前元素与整个列表中的任何元素交换,don'有。。