我遇到了这个问题,应该在棋盘上放置8个女王,这样就没有人可以互相残杀。这就是我试图解决的问题:
import itertools
def allAlive(position):
qPosition=[]
for i in range(8):
qPosition.append(position[2*i:(2*i)+2])
hDel=list(qPosition) #Horizontal
for i in range(8):
a=hDel[0]
del hDel[0]
l=len(hDel)
for j in range(l):
if a[:1]==hDel[j][:1]:
return False
vDel=list(qPosition) #Vertical
for i in range(8):
a=vDel[0]
l=len(vDel)
for j in range(l):
if a[1:2]==vDel[j][1:2]:
return False
cDel=list(qPosition) #Cross
for i in range(8):
a=cDel[0]
l=len(cDel)
for j in range(l):
if abs(ord(a[:1])-ord(cDel[j][:1]))==1 and abs(int(a[1:2])-int(cDel[j][1:2]))==1:
return False
return True
chessPositions=['A1','A2','A3','A4','A5','A6','A7','A8','B1','B2','B3','B4','B5','B6','B7','B8','C1','C2','C3','C4','C5','C6','C7','C8','D1','D2','D3','D4','D5','D6','D7','D8','E1','E2','E3','E4','E5','E6','E7','E8','F1','F2','F3','F4','F5','F6','F7','F8','G1','G2','G3','G4','G5','G6','G7','G8','H1','H2','H3','H4','H5','H6','H7','H8']
qPositions=[''.join(p) for p in itertools.combinations(chessPositions,8)]
for i in qPositions:
if allAlive(i)==True:
print(i)
追踪(最近一次呼叫最后一次):
qPositions = [''。在itertools.combinations(chessPositions,8)中为p加入(p)]
的MemoryError
我还是个新手。我怎么能克服这个错误呢?还是有更好的方法来解决这个问题?
答案 0 :(得分:4)
你要做的事情是不可能的;)!
qPositions=[''.join(p) for p in itertools.combinations(chessPositions,8)]
表示您将获得一个长度为64 choose 8 = 4426165368
的列表,因为len(chessPositions) = 64
,您无法存储在内存中。为什么不?结合我在评论中提到的内容和@augray的回答,上述操作的结果将是一个列表,
(64 choose 8) * 2 * 8 bytes ~ 66GB
RAM的,因为它将有64 choose 8
个元素,每个元素将有8个子串,如'A1'
,每个子串都包含2个字符。一个字符需要1个字节。
你必须找到另一种方式。我没有回答,因为这是你的工作。 n-queens 问题属于动态编程。我建议你google'n queens problem python'并搜索答案。然后尝试理解代码和动态编程。
我确实在搜索你,看看this video。正如@JeanFrançois-Fabre所建议的那样,回溯。你的工作现在是观看视频一次,两次......只要你不理解问题的解决方案。然后打开你喜欢的编辑器(我的是Vi:D)并编码下来!
答案 1 :(得分:4)
这是一个理解"科学" (或者更准确地说,数学)计算机科学的一部分,同样重要的是理解编程的细节。
从documentation for itertools.combinations
,我们看到返回的项目数为n! / r! / (n-r)!
,其中n
是输入集合的长度(在您的情况下,国际象棋位置的数量为64)并且r
是您想要返回的子序列的长度(在您的情况下为8)。正如@campovski指出的那样,这导致4,426,165,368。每个返回的子序列将包含8 * 2个字符,每个字符都是一个字节(更不用说保存这些字符并计算答案的其他数据结构的开销)。每个字符都是1个字节,因此总的来说,只计算结果子序列的内存消耗量4,426,165,368*2*8=70818645888
。除以1024 ^ 3得到这些子序列所占的内存Gigs数量,约为66GB。
我假设你没有那么多记忆:-)。计算这个问题的答案需要一个经过深思熟虑的算法,而不仅仅是"蛮力"。我建议对这个问题进行一些研究 - Wikipedia看起来是个好地方。
答案 2 :(得分:1)
正如其他答案所说,你不能让每一个组合都适合记忆,你不应该使用蛮力,因为速度会很慢。但是,如果你想使用蛮力,你可以约束问题,并消除常见的行和列并检查对角线
from itertools import permutations
#All possible letters
letters = ['a','b','c','d','e','f','g','h']
#All possible numbers
numbers = [str(i) for i in range(1,len(letters)+1)]
#All possible permutations given rows != to eachother and columns != to eachother
r = [zip(letters, p) for p in permutations(numbers,8)]
#Formatted for your function
points = [''.join([''.join(z) for z in b]) for b in r]
另外作为一个注释,这行代码试图首先找到所有组合,然后提供你的函数,这是浪费内存。
qPositions=[''.join(p) for p in itertools.combinations(chessPositions,8)]
如果您确定要使用蛮力方法,则可以。只需修改itertools combinations的代码即可。移除yield
和return
,然后一次只提供一个检查功能。