如何改变彩球?

时间:2011-10-21 10:50:00

标签: c# combinations

我有400个球,其中100个是红色,40个是黄色,50个是绿色,60个是蓝色,70个是紫色,80个是黑色。 (相同颜色的球是相同的)

我需要一个有效的改组算法,这样在洗牌之后,球就在列表中,并且

任何连续的3个球的颜色不同。例如,我不能有“红色,红色,红色,黄色......”

而且,所有排列都“同样”可能发生。 (好吧,如果效率与无偏见的权衡取得足够好,我不介意比无偏见更有效率。)

我试图改编Fisher-Yates-Knuth,但结果并不理想。

为什么Fisher-Yates不够好?由于FY采用蒙特卡罗逆变换。并且输出分布以不同的方式处理相同的颜色球,即它会根据我的需要产生偏差结果。

而且,天真的想法是过滤掉/回溯整个空间的所有不良排列。当限制很强时,比方说,如果我们只有300个球,其中100个是红色的,那么在进行适当的排列之前会有太多的后跟踪/失败。

所以,最终,我希望能够遍历所有良好的排列。但是,由于有效排列的数量太大,我只能随机抽样其中一些。

2 个答案:

答案 0 :(得分:2)

据我了解,FYK算法在数组中交换随机位置。为什么你不能像我在伪代码中描述的那样产生颜色?

public IEnumerable<Color> GetColors()
{
   int count = 400;
   // queue or another data structure to hold the last generated colors
   Queue<Color> lastColors = new Queue<Color>(); 
   var availableColor = new Dictionary<Color, int> { 
     {Red, 100}, {Yellow, 40}, ...
   };
   Color nextColor = null;
   while(count > 0)
   {
     do {
       /* randomly pick from color buckets */
       nextColor = /* choose random color based on the weights*/;
     } while(/*it satisfies the condition, that it is not 3rd same color in a row*/)
     yield return nextColor;
     count--;
   }
}

答案 1 :(得分:1)

大声思考,我会尝试

  • 'design'(想到)有效组合的(递归)生成器;确保它以确定的顺序生成组合;
  • 将生成器转换为确定性编号方案(唯一标识任何一个有效组合的神奇数字) 2
  • 实现生成器算法,将目标幻数作为参数,这样您就不必完成所有工作来获得'第n个有效组合',而是可以'跳转'到所需的组合(这需要你的递归生成函数显式确定性;任何回溯都会使这变得不可能。)

现在,您可以简单地在[0..max_number_of_valid_combinations] 1 之间生成均匀分布的随机“魔术”数字。对于每个选定的幻数,您可以打印生成的有效组合。

如果您有兴趣,我可能会找一些时间试试这个。 (我更喜欢在C ++ / Python中这样做,但是C#应该是可能的(.Net 4.0还有BigInteger calss吗?))


1 (这可能是一个巨大的数字,所以你可能会遇到某种类型的BigInteger,并生成多个随机数来达到大数。确保你理解分配算法到确保这仍然是均匀分布的......

2 有大量的组合数据可以得到合适的乘数,以便在生成过程中找到特定点的可能“尾部组合”的数量。这是IMO的复杂瓶颈