在坐标系中划定正方形
Delimiting a square in a coordinate system
我有一个 3 格乘 3 格的棋盘,看起来像这样:
每个正方形的边表示为一个元组,包含边的起始坐标和结束坐标,例如:
((0,0), (0,1))
不同之处在于,在任何时候都可以删除这些边中的一个。留个方块不完整。
我正在尝试在 Python 中编写一个算法来检测棋盘上的方块。
棋盘的数据保存在一个字典中,其中键是边,对应的值是布尔值,表示边当前是否在位,它看起来有点像这样:
Graph= {((0, 0), (0, 1)): True,
((0, 0), (1, 0)): True,
((0, 1), (0, 2)): True,
((0, 1), (1, 1)): True,
((0, 2), (0, 3)): True,
...}
目前,如果我遍历板上的所有点,我只能找出是否有完整的 1x1 正方形,方法是找到附近的边并检查它们是否在我的图表中设置为 True。我目前正在通过这样做找到起点附近的边缘(它总是在正方形的左下角):
((x,y)
为起点坐标)
left = ([edge for edge in graph if (x,y) in edge and (x, y+1) in edge])
right = ([edge for edge in graph if (x+1, y) in edge and (x+1, y+1) in edge])
top = ([edge for edge in graph if (x, y+1) in edge and (x+1, y+1) in edge])
down = ([edge for edge in graph if (x, y) in edge and (x+1, y) in edge])[0]
我在这里使用列表理解,因为边缘的方向目前是任意的,而不是直接访问(例如)图中的 ((1,0),(1,1))
,我需要搜索它以查看它是否具有那或 ((1,1),(1,0))
.
尽管有点复杂,但令我困扰的是我无法想出一种方法来检查更大尺寸的正方形。例如,我还需要检查 2x2 和 3x3(如果 (0,0)
是起点)正方形,因此我的方法是不可持续的。
例如,我需要检测一个从(0,0)
开始的2x2正方形,我想检测边缘为:
的正方形
left: ((0,0),(0,1)), ((0,1),(0,2))
right: ((2,0),(2,1)), ((2,1),(2,2))
top: ((0,2),(1,2)), ((1,2),(2,2))
bottom: ((0,0),(1,0)), ((1,0),(2,0))
对于混乱的代码,我深表歉意,感谢任何提示或技巧。
提前致谢。
这是一个起点。同样,这假设字典存储时元组已排序。这并不难。
def make_square( x,y,n ):
for i in range(n):
yield (x,y+i),(x,y+i+1)
yield (x+i,y),(x+i+1,y)
yield (x+n,y+i),(x+n,y+i+1)
yield (x+i,y+n),(x+i+1,y+n)
print(sorted(list(make_square(0,0,3))))
# Find 2x2.
for x in range(2):
for y in range(2):
if all(Graph[edges] for edges in make_square(x,y,2)):
print( f"2x2 Square starts at {x},{y}" )
# Find 3x3.
for x in range(1):
for y in range(1):
if all(Graph[edges] for edges in make_square(x,y,3)):
print( f"3x3 Square starts at {x},{y}" )
"make_square" returns 从 (x,y) 开始大小为 n 的正方形边的列表。它从 4 个边中的每一个边做一个片段,然后移动到下一个片段。 “产量”只是 return 一次处理多个事物的一种可爱方式。也可以将它们中的每一个存储在一个列表中,然后 return 最后是一个列表。 “收益”使它成为发电机。
因此,在底部的循环中,我们遍历了一个正方形的每个可能的起始位置。在 3x3 中,寻找 2x2 正方形,它们可以从 (0,0)、(0,1)、(1,0) 或 (1,1) 开始。
因此,对于每个起始位置,我们 make_square
为该正方形生成边。如果列表中的所有元素都为真,则“全部”函数 return 为真。因此,对于 make_square return 列表中的每条边,我们使用 Graph[edges] 的值。如果所有 return 都为真,那么“所有”return 为真,我们就有了赢家。
在最后一个循环中,3x3 正方形只有一个起始位置。我留下了循环,因为它是对称的,但当然它们不是必需的。我希望您能看到如何将其推广到更大的平方。例如,如果您有一个 5x5 的正方形:
for subsquare in range(1,5):
for x in range(5-subsquare+1):
for y in range(5-subsquare+1):
...etc...
我有一个 3 格乘 3 格的棋盘,看起来像这样:
每个正方形的边表示为一个元组,包含边的起始坐标和结束坐标,例如:
((0,0), (0,1))
不同之处在于,在任何时候都可以删除这些边中的一个。留个方块不完整。
我正在尝试在 Python 中编写一个算法来检测棋盘上的方块。
棋盘的数据保存在一个字典中,其中键是边,对应的值是布尔值,表示边当前是否在位,它看起来有点像这样:
Graph= {((0, 0), (0, 1)): True,
((0, 0), (1, 0)): True,
((0, 1), (0, 2)): True,
((0, 1), (1, 1)): True,
((0, 2), (0, 3)): True,
...}
目前,如果我遍历板上的所有点,我只能找出是否有完整的 1x1 正方形,方法是找到附近的边并检查它们是否在我的图表中设置为 True。我目前正在通过这样做找到起点附近的边缘(它总是在正方形的左下角):
((x,y)
为起点坐标)
left = ([edge for edge in graph if (x,y) in edge and (x, y+1) in edge])
right = ([edge for edge in graph if (x+1, y) in edge and (x+1, y+1) in edge])
top = ([edge for edge in graph if (x, y+1) in edge and (x+1, y+1) in edge])
down = ([edge for edge in graph if (x, y) in edge and (x+1, y) in edge])[0]
我在这里使用列表理解,因为边缘的方向目前是任意的,而不是直接访问(例如)图中的 ((1,0),(1,1))
,我需要搜索它以查看它是否具有那或 ((1,1),(1,0))
.
尽管有点复杂,但令我困扰的是我无法想出一种方法来检查更大尺寸的正方形。例如,我还需要检查 2x2 和 3x3(如果 (0,0)
是起点)正方形,因此我的方法是不可持续的。
例如,我需要检测一个从(0,0)
开始的2x2正方形,我想检测边缘为:
left: ((0,0),(0,1)), ((0,1),(0,2))
right: ((2,0),(2,1)), ((2,1),(2,2))
top: ((0,2),(1,2)), ((1,2),(2,2))
bottom: ((0,0),(1,0)), ((1,0),(2,0))
对于混乱的代码,我深表歉意,感谢任何提示或技巧。
提前致谢。
这是一个起点。同样,这假设字典存储时元组已排序。这并不难。
def make_square( x,y,n ):
for i in range(n):
yield (x,y+i),(x,y+i+1)
yield (x+i,y),(x+i+1,y)
yield (x+n,y+i),(x+n,y+i+1)
yield (x+i,y+n),(x+i+1,y+n)
print(sorted(list(make_square(0,0,3))))
# Find 2x2.
for x in range(2):
for y in range(2):
if all(Graph[edges] for edges in make_square(x,y,2)):
print( f"2x2 Square starts at {x},{y}" )
# Find 3x3.
for x in range(1):
for y in range(1):
if all(Graph[edges] for edges in make_square(x,y,3)):
print( f"3x3 Square starts at {x},{y}" )
"make_square" returns 从 (x,y) 开始大小为 n 的正方形边的列表。它从 4 个边中的每一个边做一个片段,然后移动到下一个片段。 “产量”只是 return 一次处理多个事物的一种可爱方式。也可以将它们中的每一个存储在一个列表中,然后 return 最后是一个列表。 “收益”使它成为发电机。
因此,在底部的循环中,我们遍历了一个正方形的每个可能的起始位置。在 3x3 中,寻找 2x2 正方形,它们可以从 (0,0)、(0,1)、(1,0) 或 (1,1) 开始。
因此,对于每个起始位置,我们 make_square
为该正方形生成边。如果列表中的所有元素都为真,则“全部”函数 return 为真。因此,对于 make_square return 列表中的每条边,我们使用 Graph[edges] 的值。如果所有 return 都为真,那么“所有”return 为真,我们就有了赢家。
在最后一个循环中,3x3 正方形只有一个起始位置。我留下了循环,因为它是对称的,但当然它们不是必需的。我希望您能看到如何将其推广到更大的平方。例如,如果您有一个 5x5 的正方形:
for subsquare in range(1,5):
for x in range(5-subsquare+1):
for y in range(5-subsquare+1):
...etc...