C# 如何洗牌彩色球?

C# 如何洗牌彩色球?,c#,combinations,C#,Combinations,我有400个球,其中100个是红色的,40个是黄色的,50个是绿色的,60个是蓝色的,70个是紫色的,80个是黑色的。(相同颜色的球相同) 我需要一个高效的洗牌算法,这样洗牌后,球会出现在列表中,然后 任何连续的3个球的颜色不相同。e、 g,我不能有“红,红,红,黄……” 而且,所有排列都“同等”可能发生。(好吧,如果效率与公正的权衡足够好的话,我并不介意效率高于公正) 我试图适应费舍尔·耶茨·克努斯,但结果并不理想 为什么费舍尔·耶茨不够好?As FY采用蒙特卡罗逆变换。输出分布对相同颜色的球

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

我需要一个高效的洗牌算法,这样洗牌后,球会出现在列表中,然后

任何连续的3个球的颜色不相同。e、 g,我不能有“红,红,红,黄……”

而且,所有排列都“同等”可能发生。(好吧,如果效率与公正的权衡足够好的话,我并不介意效率高于公正)

我试图适应费舍尔·耶茨·克努斯,但结果并不理想

为什么费舍尔·耶茨不够好?As FY采用蒙特卡罗逆变换。输出分布对相同颜色的球有不同的处理方式,也就是说,它会根据我的需要产生有偏差的结果

而且,天真的想法是从整个空间中过滤/回溯所有不好的排列。当限制非常强时,比如说,如果我们只有300个球,其中100个是红色的,那么在得到适当的排列之前,将会有太多的回溯/失败


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

据我所知,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--;
   }
}
public IEnumerable GetColors()
{
整数计数=400;
//队列或其他数据结构来保存最后生成的颜色
Queue lastColors=new Queue();
var availableColor=新字典{
{红色,100},{黄色,40}。。。
};
颜色nextColor=null;
而(计数>0)
{
做{
/*从颜色桶中随机挑选*/
nextColor=/*根据权重选择随机颜色*/;
}而(/*它满足条件,即它在一行中不是第三个相同的颜色*/)
下一个颜色的收益率;
计数--;
}
}

大声思考,我会试试

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

现在,您只需在[0..max\u number\u of\u valid\u compositions]1之间生成一个均匀分布的随机“幻数”。对于每个选定的幻数,可以打印生成的有效组合

如果你感兴趣的话,我可能会抽出时间来试一下。(我更喜欢用C++/Python,但C#应该是可能的(是否.NET4.0提供了BigInteger Cals?)


1(这可能是一个巨大的数字,因此您可能会被某种类型的BigInteger所困扰,并生成多个随机数以得到大的数字。请确保您了解分布算法,以确保它仍然是均匀分布的


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

您是如何尝试适应Fisher-Yates Knuth的,以及结果如何不“理想”?我认为用一个天真的解决方案,你最终会用回溯法来确保你的规则成立。想象一下,如果你还有三个球要捡,而且三个球的颜色都相同;那么,用一个简单的线性算法,你可以不保证没有三个连续的球是同一颜色的。@joey:我以前试过回溯法,但是,当对输入的限制太强,算法将需要大量时间回溯,即大量故障和错误retries@colinfang澄清问题:您是否试图实际生成一个包含400个项目的特定“洗牌”(这恰好与“一行三无”约束相匹配),或者你是在试图想出三个球的随机组合,其中特定组合的概率与“从有效的[实际的]洗牌中随机挑选三个球”的概率相同。当你跑完全程只剩下三个红球时会发生什么?我不知道-它隐藏在“根据权重选择随机颜色"…该算法的成功与否取决于输入值,使用100xR和1xG不会得到正确的结果。ur算法是经典FY算法或蒙特卡罗逆变换的一些变体。如果对输入的限制太强,将导致太多的失败,输出也会有太多的偏差,则该算法将不会有效。是的,可用。Max NoMyByOffyValueMax组合太大。我更愿意将RNG嵌入到生成器中。为了提高效率,我不介意失去一些不偏向性。毕竟,我想从10000个空间中得到唯一的排列。C++是可以的。me@colinfang:太大了,不能放什么?只需要放在实验室里不可枚举的,不可枚举的