天真洗牌的现实问题
我正在撰写许多文章,旨在通过使用与扑克相关的主题来教授入门编程概念。目前,我正在研究改组。
正如Jeff Atwood在CodingHorror.com上指出的那样,一种简单的混洗方法(遍历数组并将每个卡与数组中其他位置的随机卡交换)会产生排列不均的分布。在实际应用中,我将仅使用Knuth Fisher-Yates随机播放来获得更均匀的随机性。但是,我不想用对编码器不太友好的算法来解释编程概念。
这就引出了一个问题:如果黑帽知道我们使用的是52张牌的天真洗牌,那么黑帽将有多少优势?似乎它会无限小。
解决方案
主观。
It seems like it would be infinitesimally small.
同意。
事实证明,优势非常明显。看看这篇文章
问题的一部分是算法有缺陷,而另一部分是假设我们可以从计算机中获得"随机"数字。
并不是说我们正在编写将用于实际在线赌博网站的扑克程序。当我们教人们如何编程时,让某人在程序上作弊的能力并不重要。
留个便条说这是现实世界的不良模型(将其作为可能的安全漏洞进行引用),请继续学习。
一种简单且公平的改组算法是为卡组中的每张卡分配一个随机浮点数(例如,介于0和1之间),然后按分配的编号对卡组进行排序。
这实际上是一个让学生认识到仅仅因为直观的东西(在我们的案例中是天真的洗牌)并不意味着它是正确的例子。
顺便说一句,在ITtoolbox上有一篇关于改组的博客文章,在模拟改组时可能会引起兴趣。
至于问题,请考虑有52个!可以从此开始的卡座配置可能会在事物着陆时发挥作用,就像Jeff的3卡式卡座示例所示,请注意,过高表示的1在每个插槽中都出现一次。还请注意,他说我们必须先拥有几千个示例,才能清楚地看到优势在哪里,但是有了甲板,我们不太可能从完全相同的初始甲板重新开始,是吗?我们会拿走发牌并将其放在底部并洗牌,这在我看来不太可能重复。
与幼稚的随机播放相比,knuth随机播放是一个微不足道的更改:只需与卡牌的剩余(未随机播放)部分中的任何一张牌交换,而无需交换整个卡牌中的任何位置。如果我们将其视为从剩余未选择的卡中依次选择下一张卡,那也非常直观。
就个人而言,我认为在适当的算法不再复杂(并且更容易可视化!)的情况下,教给学生一种糟糕的算法是一种不好的方法。