我想从数组中随机选择2个名字,为数组中的所有名称执行此操作,并确保没有人与同一个人联系两次。在每个人与对方一起合作之后,重新开始大循环。
我发现.sample方法可以随机从数组中提取2个名称。 [“Sander”, “Sjaak”, “Timo”, “Ernst”, “Floris”, “Wayne”, “Arno”, “Henk”, “Rob”].sample(2)
但是,如何确保第二天人们不会与同一个人合作?
答案 0 :(得分:3)
这是棋手玩全部比赛的方式。它被称为"循环赛锦标赛"。 Wikipedia has an algorithm。可以预先对阵列进行洗牌。 这是维基百科文章的实现:
names = ["Sander", "Sjaak", "Timo", "Ernst", "Floris", "Wayne", "Arno", "Henk", "Rob"]
n = names.dup #n is going to be mutated, leave names intact
n << "Dummy" if n.size.odd?
fixed_name = n.shuffle!.pop
n.size.times do |i| #n.size is one less than the number of participants
puts "round #{i+1}"
two_rows = [[fixed_name]+n[0..n.size/2-1], n[n.size/2..-1].reverse]
pairs = two_rows.transpose.shuffle # the shuffle is optional, just cosmetic
pairs.each{|c| p c }
n.rotate!
puts
end
输出:
round 1
["Arno", "Floris"]
["Wayne", "Dummy"]
["Sander", "Sjaak"]
["Henk", "Rob"]
["Ernst", "Timo"]
round 2
["Wayne", "Sjaak"]
["Dummy", "Rob"]
["Ernst", "Arno"]
["Henk", "Floris"]
["Sander", "Timo"]
round 3
["Wayne", "Timo"]
["Henk", "Arno"]
["Rob", "Sjaak"]
["Ernst", "Sander"]
["Dummy", "Floris"]
round 4
["Wayne", "Sander"]
["Sjaak", "Floris"]
["Dummy", "Arno"]
["Rob", "Timo"]
["Ernst", "Henk"]
round 5
["Sjaak", "Arno"]
["Dummy", "Henk"]
["Floris", "Timo"]
["Rob", "Sander"]
["Ernst", "Wayne"]
round 6
["Ernst", "Dummy"]
["Timo", "Arno"]
["Rob", "Wayne"]
["Sjaak", "Henk"]
["Floris", "Sander"]
round 7
["Timo", "Henk"]
["Sjaak", "Dummy"]
["Floris", "Wayne"]
["Ernst", "Rob"]
["Arno", "Sander"]
round 8
["Ernst", "Sjaak"]
["Sander", "Henk"]
["Arno", "Wayne"]
["Floris", "Rob"]
["Timo", "Dummy"]
round 9
["Sander", "Dummy"]
["Ernst", "Floris"]
["Henk", "Wayne"]
["Arno", "Rob"]
["Timo", "Sjaak"]
答案 1 :(得分:1)
从一系列名称开始:
names = ["Sander", "Sjaak", "Timo", "Ernst", "Floris", "Wayne", "Arno", "Henk"]
你想要将它们混洗并成对分组:
shuffled = names.shuffle.each_slice(2).to_a
#=> [["Timo", "Sjaak"], ["Henk", "Arno"], ["Sander", "Ernst"], ["Wayne", "Floris"]]
到目前为止看起来不错,但是这将是一个问题,因为顺序对数组很重要。例如,[&#34; Timo&#34;,&#34; Sjaak&#34;]被认为与[&#34; Sjaak&#34;,&#34; Timo&#34;]不同。我们可以通过将数组转换为集合来解决这个问题。在确定两个集合是否相等时,顺序并不重要。
shuffled = names.shuffleeach_slice(2).map { |group| Set.new(group) }
#=> [#<Set: {"Arno", "Wayne"}>, #<Set: {"Henk", "Timo"}>, #<Set: {"Ernst", "Floris"}>, #<Set: {"Sander", "Sjaak"}>]
棘手的部分是确保每一天都没有重复。你可能有&#34;规则&#34;为了防止这种情况,但是你的算法将不再是随机的。确保完全随机性的唯一方法是检查重复和重新洗牌。我们假设您已将某一天的群组保存到yesterday
,并且您想要一个新的群组。您可以执行以下操作:
loop do
today = names.shuffle.each_slice(2).map { |group| Set.new(group) }
break if (today & yesterday).empty?
end
today & yesterday
部分称为&#34;设置相交。&#34;它将返回一个新数组,其中仅包含today
和yesterday
中相同的组。如果没有组相同(意味着没有重复),则数组将为空。
唯一剩下的就是找出如何保存昨天的小组,以便你可以用它来检查今天的小组。如果您在规定的时间范围内工作(例如,教师为学期创建学生组),那么您可以一次性计算整个学期的学生组。否则,您可能需要将前一天的群组保存到文本文件中,以便日后访问。