这是一个经典游戏的旋转尼姆它可以追溯到16世纪初,但直到1901年,哈佛大学的查尔斯·鲍顿(Charles L.Bouton)提出了“尼姆”这个名字,并围绕游戏发展了完整的数学理论。在古典尼姆币中,可以有很多堆硬币,但在你的回合中,你只能从其中一堆硬币中取出硬币。本周Riddler Classic中的“Penny Pinching”变体被称为威瑟夫的游戏围绕着它的理论非常吸引人。我会在这里用我自己的话来解释。
每个位置可以用一对$(a,b)$(每堆硬币的数量)来描述。如果我把硬币放在这种特殊的位置上是安全的,那么这个位置就叫做“安全”;无论对方做了什么,他们都不可能赢得比赛。默认情况下,$(0,0)$是安全的,因为到达这个位置意味着我赢了比赛。
例如,$(1,2)$是安全的,因为我的对手的唯一合法动作是:
- 从第一堆中取出以获得$(0,2)$。
- 从第二堆中取出以获得$(1,1)$或$(1,0)$。
- 从两个桩中取出以获得$(0,1)$。
在所有这些情况下,我们都可以一蹴而就,所以$(1,2)$是我们的安全仓位。安全仓位有两个关键属性:
- 在一次移动中,从另一个安全位置到达安全位置是不可能的。如果这是可能的,那么我们的对手可以移动到一个安全的位置,然后他们就会是安全的!
- 从任何不安全的位置,都可以一次移动到安全位置。这是因为如果我们从一个安全的位置开始,那么根据定义,无论何时再次轮到我们,我们都必须能够回到安全的位置。
生成安全位置的一种方法是绘制晶格。每个单元格$(a,b)$对应游戏的位置。如果安全,我们可以将每个单元格涂成绿色,如果不安全,我们也可以将其涂成红色。我们可以迭代地完成这项工作,首先标记$(0,0)$safe,然后按照下图所述进行操作:
以下是生成任意大小的解决方案网格的Python代码片段:
将numpy导入为npN=51#将此更改为不同的点数A=np.零((2*N,2*N),int)对于范围(2*N)内的i:对于范围(i+1)中的j:A[i-j,j]=~((A[:i-j,j]==1).any()|(A[i-j,:j]==1).any()|(np.diag(A[i-j-1::-1,j-1::-1])==1).any())
然后,我们可以使用下面的Python代码可视化网格:
将matplotlib.pyplot作为plt导入导入matplotlib.cm作为cm图,ax=plt.子图(图=(9,9))ax.imshow(A[:N,:N],原点=“低”,插值=无,cmap=厘米。蓝色)ax.set_sticks(范围(N),次要=真)ax.set_yticks(范围(N),次要=真)ax.grid(其中='minor',color='lightgray')ax.grid(其中='major',color='dimgray')ax.图([0,20],[20,0],'r--')ax.图([0,30],[30,0],'r--')ax.set_xlabel(“第一堆硬币”)ax.set_ylabel(“第二堆硬币”)ax.set_title(“捏便士中的安全组合(Wythoff的游戏)”)
得出的数字(对于$N=51$)为:
游戏开始时,我可以按他们喜欢的方式分割硬币。例如,如果有20个硬币,那么我可以沿着下方红色虚线对角线选择任何起始位置(这是两堆硬币总数都为20的位置)。因为在这条对角线上没有安全的位置,所以我不能保证安全,所以我会输。然而,如果硬币的初始数量是:3、8、11、16、21、24、29、32、37、42、45、50、55、58、63、66、71、76、79、84、87、92、97、100……(包含安全位置的对角线),那么我可以将硬币分割到一个安全位置,从而获胜。这个数字序列很有趣,它有自己的名字:Wythoff AB编号.
安全位置的分布似乎在上面的图上形成了线条,但经过仔细检查,这些点的分布没有明显的模式。然而,Wythoff能够证明这些线的斜率是$\varphi$和$\varpi^{-1}$,其中$\varfi=\tfrac{1}{2}(1+\sqrt{5})大约1.618$是黄金比例! 不仅如此,我们还可以使用以下公式生成所有安全对:
$\显示样式
\text{所有安全对的集合}(a,b)\text{with}a\leb\text{is}\quad\left
$
其中$\lfloor x\rfloor$是楼层函数,即四舍五入得到的整数。这将在上面的绘图中生成更陡峭的线条。我们可以通过交换两个坐标来获得另一半的点。这意味着,当硬币的起始数目为以下形式时,首发球员总是可以赢得比赛:
$\显示样式
\bigl\lfloor n\varphi\bigr\rfloor+\bigl\lploor n\varphi^2\bigr\rploor\quad\text{代表}n=0,1,2,\dots
$
当我们使用下面的Python代码替换上面的公式时,我们得到了Wythoff的序列:
将numpy导入为npφ=(1+np.sqrt(5))/2np.数组([int(np.floor(n*phi)+np.flower(n*φ**2)),用于范围(1118)内的n)]#输出:阵列([3、8、11、16、21、24、29、32、37、42、45、50、55、,58, 63, 66, 71, 76, 79, 84, 87, 92, 97, 100, 105, 110,113、118、121、126、131、134、139、144、147、152、155、160、165,168, 173, 176, 181, 186, 189, 194, 199, 202, 207, 210, 215, 220,223, 228, 231, 236, 241, 244, 249, 254, 257, 262, 265, 270, 275,278, 283, 288, 291, 296, 299, 304, 309, 312, 317, 320, 325, 330,333, 338, 343, 346, 351, 354, 359, 364, 367, 372, 377, 380, 385,388, 393, 398, 401, 406, 409, 414, 419, 422, 427, 432, 435, 440,443、448、453、456、461、464、469、474、477、482、487、490、495])
如果你对这个公式的原始证明感兴趣(或者对20世纪早期书面数学的迷人一瞥),这里是威瑟夫1907年的原始论文.