这款游戏背后的数学/计算原理是什么?

我的孩子有一个有趣的游戏,叫做点它!,游戏的限制条件(我能描述的最好)是:

  • 它是一副55张牌
  • 每张卡片上有8张不同的图片(即一张卡片不能有两张相同的图片)
  • 从牌组中任意选择2张牌,有且只有1张匹配的图片
  • 不同卡片上的匹配图片可能会有不同的比例,但这只会让游戏变得更难(例如,一棵小树仍然可以匹配一棵大树)

游戏的原则是:翻两张牌,谁先挑到匹配的图片就得一分。

这里有一张图片来说明:

spot it

(例如:你可以从上面最下面的两张卡片上看到,匹配的图片是绿色的恐龙。在右下角和右中间的图片之间,是一个小丑的头。)

我试图理解以下几点:

  1. 满足这些标准所需的不同图片的最少数量是多少?您将如何确定?

  2. 使用伪代码(或Ruby),如何从N张图片的数组中生成55张游戏卡(其中N是问题1中的最小数字)?

更新:

每张牌上的图片确实出现了两次以上(与一些人的猜测相反)。请看这张3张卡片的图片,每张卡片都有一个闪电:3张卡片

35230 次浏览

我刚找到一种方法来做57或58张图片,但现在我有一个非常严重的头痛,我会在我睡好后8-10个小时发布ruby代码!只是一个提示,我的解决方案,每7张卡共享相同的标记,总共56张卡可以使用我的解决方案。

下面是生成ypercube所说的全部57张卡片的代码。它使用了57张图片,抱歉,我写了实际的c++代码,但知道vector <something>是一个包含something类型值的数组,很容易理解这段代码的功能。这段代码使用P^2+P+1图片生成P^2+P+1卡,每张图片包含P+1图片,并且对于每个素数P值只共享1张图片。这意味着我们可以有7张牌使用7张图片,每张有3张图片(p=2), 13张牌使用13张图片(p=3), 31张牌使用31张图片(p=5), 57张牌使用57张图片(p=7)等等……

#include <iostream>
#include <vector>


using namespace std;


vector <vector<int> > cards;


void createcards(int p)
{
cards.resize(0);
for (int i=0;i<p;i++)
{
cards.resize(cards.size()+1);
for(int j=0;j<p;j++)
{
cards.back().push_back(i*p+j);
}
cards.back().push_back(p*p+1);
}


for (int i=0;i<p;i++)
{
for(int j=0;j<p;j++)
{
cards.resize(cards.size()+1);
for(int k=0;k<p;k++)
{
cards.back().push_back(k*p+(j+i*k)%p);
}
cards.back().push_back(p*p+2+i);
}
}


cards.resize(cards.size()+1);


for (int i=0;i<p+1;i++)
cards.back().push_back(p*p+1+i);
}


void checkCards()
{
cout << "---------------------\n";
for(unsigned i=0;i<cards.size();i++)
{
for(unsigned j=0;j<cards[i].size();j++)
{
printf("%3d",cards[i][j]);
}
cout << "\n";
}
cout << "---------------------\n";
for(unsigned i=0;i<cards.size();i++)
{
for(unsigned j=i+1;j<cards.size();j++)
{
int sim = 0;
for(unsigned k=0;k<cards[i].size();k++)
for(unsigned l=0;l<cards[j].size();l++)
if (cards[i][k] == cards[j][l])
sim ++;
if (sim != 1)
cout << "there is a problem between cards : " << i << " " << j << "\n";


}
}
}


int main()
{
int p;
for(cin >> p; p!=0;cin>> p)
{
createcards(p);
checkCards();
}
}

再次为延迟的代码感到抱歉。

所以有k = 55卡片包含m = 8图片,每个图片来自n图片池。 我们可以重申这个问题:“我们需要多少张图片n,这样我们就可以构造一组k卡片,每对卡片之间只有一张共享的图片?”'等效地问:

给定一个n维向量空间和所有向量的集合,其中包含恰好等于1和所有其他为0的元素,n有多大,以便我们可以找到一个k向量的集合,其成对点积都等于1?

有(n choose )个可能的向量来构建对。因此,我们至少需要一个足够大的n,以便(n选择) >= k。这只是一个下界,所以为了满足成对兼容性约束,我们可能需要一个更高的n

只是为了试验一下,我写了一个小Haskell程序来计算有效的卡组:

编辑:我刚刚意识到在看到尼尔和Gajet的解决方案后,我使用的算法并不总是能找到最好的解决方案,所以下面的一切并不一定有效。我会尽快更新我的代码。

module Main where


cardCandidates n m = cardCandidates' [] (n-m) m
cardCandidates' buildup  0  0 = [buildup]
cardCandidates' buildup zc oc
| zc>0 && oc>0 = zerorec ++ onerec
| zc>0         = zerorec
| otherwise    = onerec
where zerorec = cardCandidates' (0:buildup) (zc-1) oc
onerec  = cardCandidates' (1:buildup) zc (oc-1)


dot x y = sum $ zipWith (*) x y
compatible x y = dot x y == 1


compatibleCards = compatibleCards' []
compatibleCards' valid     [] = valid
compatibleCards' valid (c:cs)
| all (compatible c) valid = compatibleCards' (c:valid) cs
|                otherwise = compatibleCards'    valid  cs


legalCardSet n m = compatibleCards $ cardCandidates n m


main = mapM_ print [(n, length $ legalCardSet n m) | n<-[m..]]
where m = 8

所产生的最大兼容卡数=每张卡8张图片,对于前几张n可从n中选择不同数量的图片,如下所示:

.

由于组合爆炸,这种蛮力方法并没有走得太远。但我觉得还是很有趣的。

有趣的是,对于给定的k似乎只随n增加到一定的n,之后它保持不变。

这意味着,对于每张卡片的图片数量,都有一定数量的图片可供选择,这就导致了合法卡片的最大可能数量。增加更多的图片来选择从最优的数量并没有增加合法的卡的数量进一步。

前几个最优k是:

optimal k table

有限射影几何

射影(平面)几何公理与欧几里得几何略有不同:

  • 每两个点都有一条直线经过它们(这是一样的)。
  • 每两条直线恰好相交于一点(这与欧几里得有点不同)。

现在,将“有限”添加到汤中,你就有了问题:

我们能有一个只有两点的几何吗?3分?4吗?7吗?

关于这个问题还有一些悬而未决的问题,但我们知道这一点:

  • 如果存在具有Q点的几何图形,则Q = n^2 + n + 1n称为几何图形的order
  • 每一行都有n+1个点。
  • 从每个点开始,精确地传递n+1行。
  • 总行数也是Q

  • 最后,如果n是素数,那么确实存在一个n阶的几何。


有人可能会问,这和谜题有什么关系呢?

card代替point,用picture代替line,公理就变成:

  • 每两张卡片上恰好有一张相同的图片。
  • 对于每两张图片,恰好有一张卡片同时包含这两张图片。

现在,让我们取n=7,我们有order-7有限几何和Q = 7^2 + 7 + 1。这使得Q=57行(图片)和Q=57点(卡片)。我猜谜题制作者认为55比57更整数,所以漏掉了2张牌。

我们还得到n+1 = 8,因此从每个点(卡片),8行通过(出现8张图片),每一行(图片)有8个点(出现在8张卡片中)。


这里是最著名的有限射影(阶-2)平面(几何)的表示,有7个点,称为< >强法诺平面< / >强,复制自诺艾尔埃文斯-有限几何问题页

enter image description here

我想创建一个图像来解释上面的order-2平面如何用7张卡片和7张图片制作一个类似的谜题,然后是一个数学链接。exchange孪生问题就有这样一个图: dobble -et-la-几何-finie

范诺飞机

下面是Gajet用Python编写的解决方案,因为我觉得Python更具可读性。我对它进行了修改,使它也适用于非质数。我已经使用Thies的洞察力来生成一些更容易理解的显示代码。

from __future__ import print_function
from itertools import *


def create_cards(p):
for min_factor in range(2, 1 + int(p ** 0.5)):
if p % min_factor == 0:
break
else:
min_factor = p
cards = []
for i in range(p):
cards.append(set([i * p + j for j in range(p)] + [p * p]))
for i in range(min_factor):
for j in range(p):
cards.append(set([k * p + (j + i * k) % p
for k in range(p)] + [p * p + 1 + i]))


cards.append(set([p * p + i for i in range(min_factor + 1)]))
return cards, p * p + p + 1


def display_using_stars(cards, num_pictures):
for pictures_for_card in cards:
print("".join('*' if picture in pictures_for_card else ' '
for picture in range(num_pictures)))


def check_cards(cards):
for card, other_card in combinations(cards, 2):
if len(card & other_card) != 1:
print("Cards", sorted(card), "and", sorted(other_card),
"have intersection", sorted(card & other_card))


cards, num_pictures = create_cards(7)
display_using_stars(cards, num_pictures)
check_cards(cards)

输出:

***      *
***   *
****
*  *  *   *
*  *  *  *
*  *  * *
*   *   *  *
*   **    *
**   *   *
*    * *    *
* *    *   *
* * *     *
****

其他人描述了设计的一般框架(有限射影面),并展示了如何生成素数阶的有限射影面。我只是想填补一些空白。

有限投影平面可以生成许多不同的阶,但它们在素数阶p的情况下是最直接的。然后整数模p形成一个有限域,可用于描述平面上点和线的坐标。点有3种不同的坐标:(1,x,y)(0,1,x)(0,0,1),其中xy可以取从0p-1的值。3种不同类型的点解释了公式p^2+p+1的系统中的点的数量。我们也可以用相同的3种不同类型的坐标来描述直线:p0, p1和p2。

我们通过它们坐标的点积是否等于0 mod p来计算点和线是否相交。例如,点(1,2,5)和直线[0,1,1]1*0+2*1+5*1 = 7 == 0 mod 7之后发生了冲突,而点(1,3,3)和直线[1,2,6]1*1+3*2+3*6 = 25 != 0 mod 7之后就没有冲突。

翻译成卡片和图片的语言,这意味着坐标为(1,2,5)的图片包含在坐标为[0,1,1]的卡片中,但坐标为(1,3,3)的图片不包含在坐标为[1,2,6]的卡片中。我们可以使用这个过程来开发一个完整的卡片列表和它们所包含的图片。

我认为把图片看成点,把卡片看成线更容易,但在射影几何中,点和线之间存在对偶性,所以这并不重要。然而,在接下来的内容中,我将用点来表示图片,用线来表示卡片。

同样的构造适用于任何有限域。我们知道存在一个有限阶域q当且仅当q=p^k是质数幂。该字段被称为GF(p^k),代表“伽罗瓦字段”。在素数幂的情况下场不像在素数幂的情况下那么容易构造。

幸运的是,艰苦的工作已经在自由软件中完成并实现了,即圣人数学。例如,要得到一个4阶的射影平面设计,只需输入

PG = designs.ProjectiveGeometryDesign(2,1,GF(4),point_coordinates=0)
PG.blocks()

你会得到这样的输出

[[0,1,2,3,20], [0,4,8,12,16], [0,5,10,15,19], [0,6,11,13,17],
[0,7,9,14,18], [1,4,11,14,19], [1,5,9,13,16], [1,6,8,15,18],
[1,7,10,12,17], [2,4,9,15,17], [2,5,11,12,18], [2,6,10,14,16],
[2,7,8,13,19], [3,4,10,13,18], [3,5,8,14,17], [3,6,9,12,19],
[3,7,11,15,16], [4,5,6,7,20], [8,9,10,11,20], [12,13,14,15,20],
[16,17,18,19,20]]

我对上面的解释如下:一共有21张图片,标签从0到20。每个方块(投影几何中的线条)告诉我卡片上出现了哪些图片。例如,第一张卡片将有图片0、1、2、3和20;第二张卡片上有图片0、4、8、12和16;等等。

7阶方程组可以由

PG = designs.ProjectiveGeometryDesign(2,1,GF(7),point_coordinates=0)
PG.blocks()

生成输出

[[0, 1, 2, 3, 4, 5, 6, 56], [0, 7, 14, 21, 28, 35, 42, 49],
[0, 8, 16, 24, 32, 40, 48, 50], [0, 9, 18, 27, 29, 38, 47, 51],
[0, 10, 20, 23, 33, 36, 46, 52], [0, 11, 15,
26, 30, 41, 45, 53], [0, 12, 17, 22, 34, 39, 44, 54], [0, 13, 19, 25,
31, 37, 43, 55], [1, 7, 20, 26, 32, 38, 44, 55], [1, 8, 15, 22, 29, 36,
43, 49], [1, 9, 17, 25, 33, 41, 42, 50], [1, 10, 19, 21, 30, 39, 48,
51], [1, 11, 14, 24, 34, 37, 47, 52], [1, 12, 16, 27, 31, 35, 46, 53],
[1, 13, 18, 23, 28, 40, 45, 54], [2, 7, 19, 24, 29, 41, 46, 54], [2, 8,
14, 27, 33, 39, 45, 55], [2, 9, 16, 23, 30, 37, 44, 49], [2, 10, 18, 26,
34, 35, 43, 50], [2, 11, 20, 22, 31, 40, 42, 51], [2, 12, 15, 25, 28,
38, 48, 52], [2, 13, 17, 21, 32, 36, 47, 53], [3, 7, 18, 22, 33, 37, 48,
53], [3, 8, 20, 25, 30, 35, 47, 54], [3, 9, 15, 21, 34, 40, 46, 55], [3,
10, 17, 24, 31, 38, 45, 49], [3, 11, 19, 27, 28, 36, 44, 50], [3, 12,
14, 23, 32, 41, 43, 51], [3, 13, 16, 26, 29, 39, 42, 52], [4, 7, 17, 27,
30, 40, 43, 52], [4, 8, 19, 23, 34, 38, 42, 53], [4, 9, 14, 26, 31, 36,
48, 54], [4, 10, 16, 22, 28, 41, 47, 55], [4, 11, 18, 25, 32, 39, 46,
49], [4, 12, 20, 21, 29, 37, 45, 50], [4, 13, 15, 24, 33, 35, 44, 51],
[5, 7, 16, 25, 34, 36, 45, 51], [5, 8, 18, 21, 31, 41, 44, 52], [5, 9,
20, 24, 28, 39, 43, 53], [5, 10, 15, 27, 32, 37, 42, 54], [5, 11, 17,
23, 29, 35, 48, 55], [5, 12, 19, 26, 33, 40, 47, 49], [5, 13, 14, 22,
30, 38, 46, 50], [6, 7, 15, 23, 31, 39, 47, 50], [6, 8, 17, 26, 28, 37,
46, 51], [6, 9, 19, 22, 32, 35, 45, 52], [6, 10, 14, 25, 29, 40, 44,
53], [6, 11, 16, 21, 33, 38, 43, 54], [6, 12, 18, 24, 30, 36, 42, 55],
[6, 13, 20, 27, 34, 41, 48, 49], [7, 8, 9, 10, 11, 12, 13, 56], [14, 15,
16, 17, 18, 19, 20, 56], [21, 22, 23, 24, 25, 26, 27, 56], [28, 29, 30,
31, 32, 33, 34, 56], [35, 36, 37, 38, 39, 40, 41, 56], [42, 43, 44, 45,
46, 47, 48, 56], [49, 50, 51, 52, 53, 54, 55, 56]]

如果你想要最多57张卡,你可以使用GF(7)。如果你想要58张牌,你就必须使用更大的区域。因为8是质数的幂,你可以使用GF(8)。注意,基于GF(8)的射影平面将有8^2 + 8 + 1 = 73个点和73条线。你可以制作73张牌,但如果你想要一套58张牌,就扔掉15张。如果你想要73到91张卡片,你可以使用GF(9)等等。没有GF(10),因为10不是质数的幂。GF(11)是下一个,然后是GF(13),然后是GF(16),因为16=2^4,依此类推。

顺便说一下,我有一个理论,原来的Spot It桥牌使用55张,而不是57张,因为他们承包了一个扑克牌制造商,该制造商已经制作了55张牌的桥牌(一副桥牌中有52张普通牌,加上两张小丑牌和一张标题牌)。

使用z3定理证明

P为每张卡片的符号数。根据这篇文章ypercubeᵀᴹ的答案,分别有N = P**2 - P + 1卡片和符号。一副牌可以用它的关联矩阵表示,每个牌都有一行,每个可能的符号都有一列。如果卡片i上有符号j,那么它的(i,j)元素就是1。我们只需要记住以下约束条件来填充这个矩阵:

  • 每个元素不是0就是1
  • 每一行的和恰好是P
  • 每一列的和恰好是P
  • 任何两行必须有一个相同的符号

这意味着N**2变量和N**2 + 2*N + (N choose 2)约束。在不太长的时间内,对于小输入,使用z3似乎是可以管理的。

编辑:不幸的是,P=8对于这个方法来说似乎太大了。我在14个小时的计算时间后终止了进程。

from z3 import *
from itertools import combinations


def is_prime_exponent(K):
return K > 1 and K not in 6  # next non-prime exponent is 10,
# but that is too big anyway


def transposed(rows):
return zip(*rows)


def spotit_z3(symbols_per_card):
K = symbols_per_card - 1
N = symbols_per_card ** 2 - symbols_per_card + 1
if not is_prime_exponent(K):
raise TypeError("Symbols per card must be a prime exponent plus one.")


constraints = []


# the rows of the incidence matrix
s = N.bit_length()
rows = [[BitVec("r%dc%d" % (r, c), s) for c in range(N)] for r in range(N)]


# every element must be either 1 or 0
constraints += [Or([elem == 1, elem == 0]) for row in rows for elem in row]


# sum of rows and cols must be exactly symbols_per_card
constraints += [Sum(row) == symbols_per_card for row in rows]
constraints += [Sum(col) == symbols_per_card for col in transposed(rows)]


# Any two rows must have exactly one symbol in common, in other words they
# differ in (symbols_per_card - 1) symbols, so their element-wise XOR will
# have 2 * (symbols_per_card - 1) ones.
D = 2 * (symbols_per_card - 1)
for row_a, row_b in combinations(rows, 2):
constraints += [Sum([a ^ b for a, b in zip(row_a, row_b)]) == D]


solver = Solver()
solver.add(constraints)


if solver.check() == unsat:
raise RuntimeError("Could not solve it :(")


# create the incidence matrix
model = solver.model()
return [[model[elem].as_long() for elem in row] for row in rows]




if __name__ == "__main__":
import sys
symbols_per_card = int(sys.argv[1])
incidence_matrix = spotit_z3(symbols_per_card)
for row in incidence_matrix:
print(row)

结果

$python spotit_z3.py 3
[0, 0, 1, 1, 0, 1, 0]
[0, 0, 0, 0, 1, 1, 1]
[0, 1, 0, 1, 0, 0, 1]
[1, 1, 0, 0, 0, 1, 0]
[0, 1, 1, 0, 1, 0, 0]
[1, 0, 0, 1, 1, 0, 0]
[1, 0, 1, 0, 0, 0, 1]
python spotit_z3.py 3  1.12s user 0.06s system 96% cpu 1.225 total


$ time python3 spotit_z3.py 4
[0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0]
[0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0]
[0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1]
[0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0]
[0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1]
[0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1]
[0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0]
[0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0]
[1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
[1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0]
[1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0]
[1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0]
python spotit_z3.py 4  664.62s user 0.15s system 99% cpu 11:04.88 total


$ time python3 spotit_z3.py 5
[1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0]
[0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0]
[0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0]
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0]
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1]
[0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]
[0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0]
[0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1]
[1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0]
[0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0]
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0]
[0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1]
[1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0]
[0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0]
[0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1]
[1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0]
python spotit_z3.py 5  1162.72s user 20.34s system 99% cpu 19:43.39 total


$ time python3 spotit_z3.py 8
<I killed it after 14 hours of run time.>

对于那些难以用57个点描绘投影平面几何的人来说,有一个非常好的,直观的方法来构造57张卡片和57个符号的游戏(基于尤Filmus这个问题的回答):

  1. 对于8个符号的卡片,创建一个7x7的唯一符号网格。
  2. 为从0到6的“斜率”添加额外的8个符号,加上一个表示无穷大斜率。
  3. 每张卡片是网格上的一条线(7个符号)加上斜率集中的一个符号表示这条线的斜率。直线有一个偏移量(即左边的起点)和一个斜率(即每向右一步要上升多少个符号)。当行在顶部离开网格时,在底部重新输入。请看下面的示例图(图片来自boardgamegeek),有两张这样的卡片:

两张示例卡(红色和绿色)从网格中取线

在这个例子中,我取一条斜率为0的直线(红色)和一条斜率为1的直线(绿色)。它们恰好相交于一个共同点(猫头鹰)。

这种方法确保任何两张卡都有一个共同的符号,因为

  1. 如果斜率不同,那么直线总是相交于一点。
  2. 如果斜率相同,那么这两条线就不会相交,网格中也就没有共同的符号。在这种情况下,斜率符号是一样的。

这样,我们就可以构造7x7张牌(7张偏移和7张斜率)。

我们还可以从网格中的垂直线(即每一列)中构造另外7张纸牌。对于这些,使用无穷斜率图标。

因为每张卡片由来自网格的7个符号和恰好一个“斜率”符号组成,所以我们可以创建另外一张卡片,它由所有8个斜率符号组成。

这样我们就有7x8 + 1 = 57张可能的卡片,7x 7 + 8 = 57个需要的符号。

(当然,这只适用于质数大小的网格(例如n=7)。否则,如果斜率是网格大小的除数,不同斜率的线可能有0个或多个交集。)

我非常喜欢这个帖子。我用这个github python项目的部分代码在这里绘制自定义卡片为png(这样就可以在互联网上订购自定义卡片游戏)。

https://github.com/plagtag/ProjectiveGeometry-Game

我写了一个文章关于如何生成这种甲板,用Perl代码。代码没有优化,但它至少能够生成“合理”订单的甲板……还有更多。

这是一个8阶的例子,它需要考虑稍微复杂一点的基础数学,因为8不是质数尽管这是生成这种牌组的有效顺序。查看上面的文章或更详细的解释,如果你只是想生成一个稍微难一点的Spot-It:-)

$ time pg2 8
elements in field: 8
0. (1, 9, 17, 25, 33, 41, 49, 57, 65)
1. (0, 9, 10, 11, 12, 13, 14, 15, 16)
2. (2, 9, 18, 27, 36, 45, 54, 63, 72)
3. (6, 9, 22, 26, 37, 43, 56, 60, 71)
4. (7, 9, 23, 32, 34, 46, 52, 59, 69)
5. (8, 9, 24, 30, 35, 42, 55, 61, 68)
6. (3, 9, 19, 29, 39, 44, 50, 64, 70)
7. (4, 9, 20, 31, 38, 48, 53, 58, 67)
8. (5, 9, 21, 28, 40, 47, 51, 62, 66)
9. (0, 1, 2, 3, 4, 5, 6, 7, 8)
10. (1, 10, 18, 26, 34, 42, 50, 58, 66)
11. (1, 14, 22, 30, 38, 46, 54, 62, 70)
12. (1, 15, 23, 31, 39, 47, 55, 63, 71)
13. (1, 16, 24, 32, 40, 48, 56, 64, 72)
14. (1, 11, 19, 27, 35, 43, 51, 59, 67)
15. (1, 12, 20, 28, 36, 44, 52, 60, 68)
16. (1, 13, 21, 29, 37, 45, 53, 61, 69)
17. (0, 17, 18, 19, 20, 21, 22, 23, 24)
18. (2, 10, 17, 28, 35, 46, 53, 64, 71)
19. (6, 14, 17, 29, 34, 48, 51, 63, 68)
20. (7, 15, 17, 26, 40, 44, 54, 61, 67)
21. (8, 16, 17, 27, 38, 47, 50, 60, 69)
22. (3, 11, 17, 31, 37, 42, 52, 62, 72)
23. (4, 12, 17, 30, 39, 45, 56, 59, 66)
24. (5, 13, 17, 32, 36, 43, 55, 58, 70)
25. (0, 49, 50, 51, 52, 53, 54, 55, 56)
26. (3, 10, 20, 30, 40, 43, 49, 63, 69)
27. (2, 14, 21, 32, 39, 42, 49, 60, 67)
28. (8, 15, 18, 28, 37, 48, 49, 59, 70)
29. (6, 16, 19, 31, 36, 46, 49, 61, 66)
30. (5, 11, 23, 26, 38, 45, 49, 64, 68)
31. (7, 12, 22, 29, 35, 47, 49, 58, 72)
32. (4, 13, 24, 27, 34, 44, 49, 62, 71)
33. (0, 57, 58, 59, 60, 61, 62, 63, 64)
34. (4, 10, 19, 32, 37, 47, 54, 57, 68)
35. (5, 14, 18, 31, 35, 44, 56, 57, 69)
36. (2, 15, 24, 29, 38, 43, 52, 57, 66)
37. (3, 16, 22, 28, 34, 45, 55, 57, 67)
38. (7, 11, 21, 30, 36, 48, 50, 57, 71)
39. (6, 12, 23, 27, 40, 42, 53, 57, 70)
40. (8, 13, 20, 26, 39, 46, 51, 57, 72)
41. (0, 65, 66, 67, 68, 69, 70, 71, 72)
42. (5, 10, 22, 27, 39, 48, 52, 61, 65)
43. (3, 14, 24, 26, 36, 47, 53, 59, 65)
44. (6, 15, 20, 32, 35, 45, 50, 62, 65)
45. (2, 16, 23, 30, 37, 44, 51, 58, 65)
46. (4, 11, 18, 29, 40, 46, 55, 60, 65)
47. (8, 12, 21, 31, 34, 43, 54, 64, 65)
48. (7, 13, 19, 28, 38, 42, 56, 63, 65)
49. (0, 25, 26, 27, 28, 29, 30, 31, 32)
50. (6, 10, 21, 25, 38, 44, 55, 59, 72)
51. (8, 14, 19, 25, 40, 45, 52, 58, 71)
52. (4, 15, 22, 25, 36, 42, 51, 64, 69)
53. (7, 16, 18, 25, 39, 43, 53, 62, 68)
54. (2, 11, 20, 25, 34, 47, 56, 61, 70)
55. (5, 12, 24, 25, 37, 46, 50, 63, 67)
56. (3, 13, 23, 25, 35, 48, 54, 60, 66)
57. (0, 33, 34, 35, 36, 37, 38, 39, 40)
58. (7, 10, 24, 31, 33, 45, 51, 60, 70)
59. (4, 14, 23, 28, 33, 43, 50, 61, 72)
60. (3, 15, 21, 27, 33, 46, 56, 58, 68)
61. (5, 16, 20, 29, 33, 42, 54, 59, 71)
62. (8, 11, 22, 32, 33, 44, 53, 63, 66)
63. (2, 12, 19, 26, 33, 48, 55, 62, 69)
64. (6, 13, 18, 30, 33, 47, 52, 64, 67)
65. (0, 41, 42, 43, 44, 45, 46, 47, 48)
66. (8, 10, 23, 29, 36, 41, 56, 62, 67)
67. (7, 14, 20, 27, 37, 41, 55, 64, 66)
68. (5, 15, 19, 30, 34, 41, 53, 60, 72)
69. (4, 16, 21, 26, 35, 41, 52, 63, 70)
70. (6, 11, 24, 28, 39, 41, 54, 58, 69)
71. (3, 12, 18, 32, 38, 41, 51, 61, 71)
72. (2, 13, 22, 31, 40, 41, 50, 59, 68)
errors in check: 0


real    0m0.303s
user    0m0.200s
sys 0m0.016s

072的每个标识符都可以被读取为卡片标识符和图片标识符。例如,最后一行表示:

  • 卡片72包含图片21322,…, __abc4, __abc5,和
  • 图片72出现在卡片21322,…、5968

我写了下面的代码来计算卡片。这个想法是创建第一张卡片,上面有n个图像。如果每对图像索引的差值是唯一的,那么剩下的卡片就可以简单地生成,通过模m = n * n - n + 1,用相同的值增加每个索引

static public int[] Backtrack(int n)
{
int m = n * n - n + 1;
int[] Check = new int[m];
int C = 1;
int[] T = new int[n];
int _p = 2;
T[1] = 1;
if (n > 2) T[2] = 1;
else return T;
while (_p >= 2)
{
T[_p]++;
if (T[_p] == m)
{
_p--;
continue;
}
bool good = true;
C++;
for (int i = 0; i <= _p; i++)
{
for (int j = 0; j < i; j++)
{
int x = (T[i] - T[j] + m) % m;
if (Check[x] == C || Check[m - x] == C)//x cannot be equal to m-x as m is odd.
good = false;
Check[m - x] = C;
Check[x] = C;
}
}
if (good)
{
_p++;
if (_p == n)
{
_p--;
return T;
}
T[_p] = T[_p - 1];
}


}
return new int[] { };
}
static void Main(string[] args)
{
for (int N = 2; N < 11; N++)
{
var X = Backtrack(N);
if (X.Length > 0)
{
int K = N * N - N + 1;
Console.WriteLine("Cards: {0} Order {1}:", K, N - 1);
int C = 0;
for (int j = 0; j < K; j++)
{
Console.Write("Card {0:000}:", C++);
for (int i = 0; i < N; i++)
{
var t = (X[i] + j) % K;
if (j != 0 && Array.Exists(X, x => (x == t)))
Console.ForegroundColor = ConsoleColor.Green;
Console.Write("\t{0}", t);
Console.ResetColor();
}
Console.WriteLine();
}
}


}
}

输出:

Cards: 3 Order 1:
Card 000:   0   1
Card 001:   1   2
Card 002:   2   0
Cards: 7 Order 2:
Card 000:   0   1   3
Card 001:   1   2   4
Card 002:   2   3   5
Card 003:   3   4   6
Card 004:   4   5   0
Card 005:   5   6   1
Card 006:   6   0   2
Cards: 13 Order 3:
Card 000:   0   1   3   9
Card 001:   1   2   4   10
Card 002:   2   3   5   11
Card 003:   3   4   6   12
Card 004:   4   5   7   0
Card 005:   5   6   8   1
Card 006:   6   7   9   2
Card 007:   7   8   10  3
Card 008:   8   9   11  4
Card 009:   9   10  12  5
Card 010:   10  11  0   6
Card 011:   11  12  1   7
Card 012:   12  0   2   8
Cards: 21 Order 4:
Card 000:   0   1   4   14  16
Card 001:   1   2   5   15  17
Card 002:   2   3   6   16  18
Card 003:   3   4   7   17  19
Card 004:   4   5   8   18  20
Card 005:   5   6   9   19  0
Card 006:   6   7   10  20  1
Card 007:   7   8   11  0   2
Card 008:   8   9   12  1   3
Card 009:   9   10  13  2   4
Card 010:   10  11  14  3   5
Card 011:   11  12  15  4   6
Card 012:   12  13  16  5   7
Card 013:   13  14  17  6   8
Card 014:   14  15  18  7   9
Card 015:   15  16  19  8   10
Card 016:   16  17  20  9   11
Card 017:   17  18  0   10  12
Card 018:   18  19  1   11  13
Card 019:   19  20  2   12  14
Card 020:   20  0   3   13  15
Cards: 31 Order 5:
Card 000:   0   1   3   8   12  18
Card 001:   1   2   4   9   13  19
Card 002:   2   3   5   10  14  20
Card 003:   3   4   6   11  15  21
Card 004:   4   5   7   12  16  22
Card 005:   5   6   8   13  17  23
Card 006:   6   7   9   14  18  24
Card 007:   7   8   10  15  19  25
Card 008:   8   9   11  16  20  26
Card 009:   9   10  12  17  21  27
Card 010:   10  11  13  18  22  28
Card 011:   11  12  14  19  23  29
Card 012:   12  13  15  20  24  30
Card 013:   13  14  16  21  25  0
Card 014:   14  15  17  22  26  1
Card 015:   15  16  18  23  27  2
Card 016:   16  17  19  24  28  3
Card 017:   17  18  20  25  29  4
Card 018:   18  19  21  26  30  5
Card 019:   19  20  22  27  0   6
Card 020:   20  21  23  28  1   7
Card 021:   21  22  24  29  2   8
Card 022:   22  23  25  30  3   9
Card 023:   23  24  26  0   4   10
Card 024:   24  25  27  1   5   11
Card 025:   25  26  28  2   6   12
Card 026:   26  27  29  3   7   13
Card 027:   27  28  30  4   8   14
Card 028:   28  29  0   5   9   15
Card 029:   29  30  1   6   10  16
Card 030:   30  0   2   7   11  17
Cards: 57 Order 7:
Card 000:   0   1   3   13  32  36  43  52
Card 001:   1   2   4   14  33  37  44  53
Card 002:   2   3   5   15  34  38  45  54
Card 003:   3   4   6   16  35  39  46  55
Card 004:   4   5   7   17  36  40  47  56
Card 005:   5   6   8   18  37  41  48  0
Card 006:   6   7   9   19  38  42  49  1
Card 007:   7   8   10  20  39  43  50  2
Card 008:   8   9   11  21  40  44  51  3
Card 009:   9   10  12  22  41  45  52  4
Card 010:   10  11  13  23  42  46  53  5
Card 011:   11  12  14  24  43  47  54  6
Card 012:   12  13  15  25  44  48  55  7
Card 013:   13  14  16  26  45  49  56  8
Card 014:   14  15  17  27  46  50  0   9
Card 015:   15  16  18  28  47  51  1   10
Card 016:   16  17  19  29  48  52  2   11
Card 017:   17  18  20  30  49  53  3   12
Card 018:   18  19  21  31  50  54  4   13
Card 019:   19  20  22  32  51  55  5   14
Card 020:   20  21  23  33  52  56  6   15
Card 021:   21  22  24  34  53  0   7   16
Card 022:   22  23  25  35  54  1   8   17
Card 023:   23  24  26  36  55  2   9   18
Card 024:   24  25  27  37  56  3   10  19
Card 025:   25  26  28  38  0   4   11  20
Card 026:   26  27  29  39  1   5   12  21
Card 027:   27  28  30  40  2   6   13  22
Card 028:   28  29  31  41  3   7   14  23
Card 029:   29  30  32  42  4   8   15  24
Card 030:   30  31  33  43  5   9   16  25
Card 031:   31  32  34  44  6   10  17  26
Card 032:   32  33  35  45  7   11  18  27
Card 033:   33  34  36  46  8   12  19  28
Card 034:   34  35  37  47  9   13  20  29
Card 035:   35  36  38  48  10  14  21  30
Card 036:   36  37  39  49  11  15  22  31
Card 037:   37  38  40  50  12  16  23  32
Card 038:   38  39  41  51  13  17  24  33
Card 039:   39  40  42  52  14  18  25  34
Card 040:   40  41  43  53  15  19  26  35
Card 041:   41  42  44  54  16  20  27  36
Card 042:   42  43  45  55  17  21  28  37
Card 043:   43  44  46  56  18  22  29  38
Card 044:   44  45  47  0   19  23  30  39
Card 045:   45  46  48  1   20  24  31  40
Card 046:   46  47  49  2   21  25  32  41
Card 047:   47  48  50  3   22  26  33  42
Card 048:   48  49  51  4   23  27  34  43
Card 049:   49  50  52  5   24  28  35  44
Card 050:   50  51  53  6   25  29  36  45
Card 051:   51  52  54  7   26  30  37  46
Card 052:   52  53  55  8   27  31  38  47
Card 053:   53  54  56  9   28  32  39  48
Card 054:   54  55  0   10  29  33  40  49
Card 055:   55  56  1   11  30  34  41  50
Card 056:   56  0   2   12  31  35  42  51
Cards: 73 Order 8:
Card 000:   0   1   3   7   15  31  36  54  63
Card 001:   1   2   4   8   16  32  37  55  64
Card 002:   2   3   5   9   17  33  38  56  65
Card 003:   3   4   6   10  18  34  39  57  66
Card 004:   4   5   7   11  19  35  40  58  67
Card 005:   5   6   8   12  20  36  41  59  68
Card 006:   6   7   9   13  21  37  42  60  69
Card 007:   7   8   10  14  22  38  43  61  70
Card 008:   8   9   11  15  23  39  44  62  71
Card 009:   9   10  12  16  24  40  45  63  72
Card 010:   10  11  13  17  25  41  46  64  0
Card 011:   11  12  14  18  26  42  47  65  1
Card 012:   12  13  15  19  27  43  48  66  2
Card 013:   13  14  16  20  28  44  49  67  3
Card 014:   14  15  17  21  29  45  50  68  4
Card 015:   15  16  18  22  30  46  51  69  5
Card 016:   16  17  19  23  31  47  52  70  6
Card 017:   17  18  20  24  32  48  53  71  7
Card 018:   18  19  21  25  33  49  54  72  8
Card 019:   19  20  22  26  34  50  55  0   9
Card 020:   20  21  23  27  35  51  56  1   10
Card 021:   21  22  24  28  36  52  57  2   11
Card 022:   22  23  25  29  37  53  58  3   12
Card 023:   23  24  26  30  38  54  59  4   13
Card 024:   24  25  27  31  39  55  60  5   14
Card 025:   25  26  28  32  40  56  61  6   15
Card 026:   26  27  29  33  41  57  62  7   16
Card 027:   27  28  30  34  42  58  63  8   17
Card 028:   28  29  31  35  43  59  64  9   18
Card 029:   29  30  32  36  44  60  65  10  19
Card 030:   30  31  33  37  45  61  66  11  20
Card 031:   31  32  34  38  46  62  67  12  21
Card 032:   32  33  35  39  47  63  68  13  22
Card 033:   33  34  36  40  48  64  69  14  23
Card 034:   34  35  37  41  49  65  70  15  24
Card 035:   35  36  38  42  50  66  71  16  25
Card 036:   36  37  39  43  51  67  72  17  26
Card 037:   37  38  40  44  52  68  0   18  27
Card 038:   38  39  41  45  53  69  1   19  28
Card 039:   39  40  42  46  54  70  2   20  29
Card 040:   40  41  43  47  55  71  3   21  30
Card 041:   41  42  44  48  56  72  4   22  31
Card 042:   42  43  45  49  57  0   5   23  32
Card 043:   43  44  46  50  58  1   6   24  33
Card 044:   44  45  47  51  59  2   7   25  34
Card 045:   45  46  48  52  60  3   8   26  35
Card 046:   46  47  49  53  61  4   9   27  36
Card 047:   47  48  50  54  62  5   10  28  37
Card 048:   48  49  51  55  63  6   11  29  38
Card 049:   49  50  52  56  64  7   12  30  39
Card 050:   50  51  53  57  65  8   13  31  40
Card 051:   51  52  54  58  66  9   14  32  41
Card 052:   52  53  55  59  67  10  15  33  42
Card 053:   53  54  56  60  68  11  16  34  43
Card 054:   54  55  57  61  69  12  17  35  44
Card 055:   55  56  58  62  70  13  18  36  45
Card 056:   56  57  59  63  71  14  19  37  46
Card 057:   57  58  60  64  72  15  20  38  47
Card 058:   58  59  61  65  0   16  21  39  48
Card 059:   59  60  62  66  1   17  22  40  49
Card 060:   60  61  63  67  2   18  23  41  50
Card 061:   61  62  64  68  3   19  24  42  51
Card 062:   62  63  65  69  4   20  25  43  52
Card 063:   63  64  66  70  5   21  26  44  53
Card 064:   64  65  67  71  6   22  27  45  54
Card 065:   65  66  68  72  7   23  28  46  55
Card 066:   66  67  69  0   8   24  29  47  56
Card 067:   67  68  70  1   9   25  30  48  57
Card 068:   68  69  71  2   10  26  31  49  58
Card 069:   69  70  72  3   11  27  32  50  59
Card 070:   70  71  0   4   12  28  33  51  60
Card 071:   71  72  1   5   13  29  34  52  61
Card 072:   72  0   2   6   14  30  35  53  62
Cards: 91 Order 9:
Card 000:   0   1   3   9   27  49  56  61  77  81
Card 001:   1   2   4   10  28  50  57  62  78  82
Card 002:   2   3   5   11  29  51  58  63  79  83
Card 003:   3   4   6   12  30  52  59  64  80  84
Card 004:   4   5   7   13  31  53  60  65  81  85
Card 005:   5   6   8   14  32  54  61  66  82  86
Card 006:   6   7   9   15  33  55  62  67  83  87
Card 007:   7   8   10  16  34  56  63  68  84  88
Card 008:   8   9   11  17  35  57  64  69  85  89
Card 009:   9   10  12  18  36  58  65  70  86  90
Card 010:   10  11  13  19  37  59  66  71  87  0
Card 011:   11  12  14  20  38  60  67  72  88  1
Card 012:   12  13  15  21  39  61  68  73  89  2
Card 013:   13  14  16  22  40  62  69  74  90  3
Card 014:   14  15  17  23  41  63  70  75  0   4
Card 015:   15  16  18  24  42  64  71  76  1   5
Card 016:   16  17  19  25  43  65  72  77  2   6
Card 017:   17  18  20  26  44  66  73  78  3   7
Card 018:   18  19  21  27  45  67  74  79  4   8
Card 019:   19  20  22  28  46  68  75  80  5   9
Card 020:   20  21  23  29  47  69  76  81  6   10
Card 021:   21  22  24  30  48  70  77  82  7   11
Card 022:   22  23  25  31  49  71  78  83  8   12
Card 023:   23  24  26  32  50  72  79  84  9   13
Card 024:   24  25  27  33  51  73  80  85  10  14
Card 025:   25  26  28  34  52  74  81  86  11  15
Card 026:   26  27  29  35  53  75  82  87  12  16
Card 027:   27  28  30  36  54  76  83  88  13  17
Card 028:   28  29  31  37  55  77  84  89  14  18
Card 029:   29  30  32  38  56  78  85  90  15  19
Card 030:   30  31  33  39  57  79  86  0   16  20
Card 031:   31  32  34  40  58  80  87  1   17  21
Card 032:   32  33  35  41  59  81  88  2   18  22
Card 033:   33  34  36  42  60  82  89  3   19  23
Card 034:   34  35  37  43  61  83  90  4   20  24
Card 035:   35  36  38  44  62  84  0   5   21  25
Card 036:   36  37  39  45  63  85  1   6   22  26
Card 037:   37  38  40  46  64  86  2   7   23  27
Card 038:   38  39  41  47  65  87  3   8   24  28
Card 039:   39  40  42  48  66  88  4   9   25  29
Card 040:   40  41  43  49  67  89  5   10  26  30
Card 041:   41  42  44  50  68  90  6   11  27  31
Card 042:   42  43  45  51  69  0   7   12  28  32
Card 043:   43  44  46  52  70  1   8   13  29  33
Card 044:   44  45  47  53  71  2   9   14  30  34
Card 045:   45  46  48  54  72  3   10  15  31  35
Card 046:   46  47  49  55  73  4   11  16  32  36
Card 047:   47  48  50  56  74  5   12  17  33  37
Card 048:   48  49  51  57  75  6   13  18  34  38
Card 049:   49  50  52  58  76  7   14  19  35  39
Card 050:   50  51  53  59  77  8   15  20  36  40
Card 051:   51  52  54  60  78  9   16  21  37  41
Card 052:   52  53  55  61  79  10  17  22  38  42
Card 053:   53  54  56  62  80  11  18  23  39  43
Card 054:   54  55  57  63  81  12  19  24  40  44
Card 055:   55  56  58  64  82  13  20  25  41  45
Card 056:   56  57  59  65  83  14  21  26  42  46
Card 057:   57  58  60  66  84  15  22  27  43  47
Card 058:   58  59  61  67  85  16  23  28  44  48
Card 059:   59  60  62  68  86  17  24  29  45  49
Card 060:   60  61  63  69  87  18  25  30  46  50
Card 061:   61  62  64  70  88  19  26  31  47  51
Card 062:   62  63  65  71  89  20  27  32  48  52
Card 063:   63  64  66  72  90  21  28  33  49  53
Card 064:   64  65  67  73  0   22  29  34  50  54
Card 065:   65  66  68  74  1   23  30  35  51  55
Card 066:   66  67  69  75  2   24  31  36  52  56
Card 067:   67  68  70  76  3   25  32  37  53  57
Card 068:   68  69  71  77  4   26  33  38  54  58
Card 069:   69  70  72  78  5   27  34  39  55  59
Card 070:   70  71  73  79  6   28  35  40  56  60
Card 071:   71  72  74  80  7   29  36  41  57  61
Card 072:   72  73  75  81  8   30  37  42  58  62
Card 073:   73  74  76  82  9   31  38  43  59  63
Card 074:   74  75  77  83  10  32  39  44  60  64
Card 075:   75  76  78  84  11  33  40  45  61  65
Card 076:   76  77  79  85  12  34  41  46  62  66
Card 077:   77  78  80  86  13  35  42  47  63  67
Card 078:   78  79  81  87  14  36  43  48  64  68
Card 079:   79  80  82  88  15  37  44  49  65  69
Card 080:   80  81  83  89  16  38  45  50  66  70
Card 081:   81  82  84  90  17  39  46  51  67  71
Card 082:   82  83  85  0   18  40  47  52  68  72
Card 083:   83  84  86  1   19  41  48  53  69  73
Card 084:   84  85  87  2   20  42  49  54  70  74
Card 085:   85  86  88  3   21  43  50  55  71  75
Card 086:   86  87  89  4   22  44  51  56  72  76
Card 087:   87  88  90  5   23  45  52  57  73  77
Card 088:   88  89  0   6   24  46  53  58  74  78
Card 089:   89  90  1   7   25  47  54  59  75  79
Card 090:   90  0   2   8   26  48  55  60  76  80