我正在尝试用python-donaldknuth的算法在不超过5步的时间内实现代码破译。我已经检查过我的代码好几次了,它似乎遵循算法,正如这里所述: http://en.wikipedia.org/wiki/Mastermind_(board_game)#Five-guess_algorithm
然而,我知道有些秘密需要7步甚至8步才能完成。代码如下:
#returns how many bulls and cows there are
def HowManyBc(guess,secret):
invalid=max(guess)+1
bulls=0
cows=0
r=0
while r<4:
if guess[r]==secret[r]:
bulls=bulls+1
secret[r]=invalid
guess[r]=invalid
r=r+1
r=0
while r<4:
p=0
while p<4:
if guess[r]==secret[p] and guess[r]!=invalid:
cows=cows+1
secret[p]=invalid
break
p=p+1
r=r+1
return [bulls,cows]
# sends every BC to its index in HMList
def Adjustment(BC1):
if BC1==[0,0]:
return 0
elif BC1==[0,1]:
return 1
elif BC1==[0,2]:
return 2
elif BC1==[0,3]:
return 3
elif BC1==[0,4]:
return 4
elif BC1==[1,0]:
return 5
elif BC1==[1,1]:
return 6
elif BC1==[1,2]:
return 7
elif BC1==[1,3]:
return 8
elif BC1==[2,0]:
return 9
elif BC1==[2,1]:
return 10
elif BC1==[2,2]:
return 11
elif BC1==[3,0]:
return 12
elif BC1==[4,0]:
return 13
# sends every index in HMList to its BC
def AdjustmentInverse(place):
if place==0:
return [0,0]
elif place==1:
return [0,1]
elif place==2:
return [0,2]
elif place==3:
return [0,3]
elif place==4:
return [0,4]
elif place==5:
return [1,0]
elif place==6:
return [1,1]
elif place==7:
return [1,2]
elif place==8:
return [1,3]
elif place==9:
return [2,0]
elif place==10:
return [2,1]
elif place==11:
return [2,2]
elif place==12:
return [3,0]
elif place==13:
return [4,0]
# gives minimum of positive list without including its zeros
def MinimumNozeros(List1):
minimum=max(List1)+1
for item in List1:
if item!=0 and item<minimum:
minimum=item
return minimum
#list with all possible guesses
allList=[]
for i0 in range(0,6):
for i1 in range(0,6):
for i2 in range(0,6):
for i3 in range(0,6):
allList.append([i0,i1,i2,i3])
TempList=[[0,0,5,4]]
for secret in TempList:
guess=[0,0,1,1]
BC=HowManyBc(guess[:],secret[:])
counter=1
optionList=[]
for i0 in range(0,6):
for i1 in range(0,6):
for i2 in range(0,6):
for i3 in range(0,6):
optionList.append([i0,i1,i2,i3])
while BC!=[4,0]:
dummyList=[] #list with possible secrets for this guess
for i0 in range(0,6):
for i1 in range(0,6):
for i2 in range(0,6):
for i3 in range(0,6):
opSecret=[i0,i1,i2,i3]
if HowManyBc(guess[:],opSecret[:])==BC:
dummyList.append(opSecret)
List1=[item for item in optionList if item in dummyList]
optionList=List1[:] # intersection of optionList and dummyList
item1Max=0
for item1 in allList:
ListBC=[] # [list of all [bulls,cows] in optionList
for item2 in optionList:
ListBC.append(HowManyBc(item1[:],item2[:]))
HMList=[0]*14 # counts how many B/C there are for item2 in optionList
for BC1 in ListBC:
index=Adjustment(BC1)
HMList[index]=HMList[index]+1
m=max(HMList)#maximum [B,C], more left - less eliminated (min in minimax)
maxList=[i for i, j in enumerate(HMList) if j == m]
maxElement=maxList[0] #index with max
possibleGuess=[]
if m>item1Max: #max of the guesses, the max in minimax
item1Max=m
possibleGuess=[i[:] for i in optionList if AdjustmentInverse(maxElement)==HowManyBc(item1[:],i[:])]
nextGuess=possibleGuess[0][:]
guess=nextGuess[:]
BC=HowManyBc(guess[:],secret[:])
counter=counter+1
我得到:
[5,3,3,4]的计数器是7
[5,4,4,5]的计数器是8
如果有人能帮忙,我会非常感激的!在
谢谢,迈克
1。你的实现有什么问题
有四个错误。在
这一行的评论是错误的:
这实际上是minimax中的“max”(应该在调用
max
时清除)。你在试图找到一个猜想,那就是最小化产生相同评价的一组可能的秘密的最大规模。这里我们找到了组的最大大小,这就是“最大值”。这个错误让你犯了这个错误:
^{pr2}$这里你需要取最小值,而不是最大值。
在下面的行中,您从
optionList
中选择第一个将生成与item1
相同的计算结果的项:但这是不对的:我们在这里想要的猜测是
item1
,而不是其他会产生相同评估的猜测!最后,您无法正确处理
optionList
只有一个剩余项的情况。在这种情况下,所有可能的猜测都能很好地区分这一项,因此minimax过程不区分猜测。在这种情况下,您应该猜测optionList[0]
。2。对代码的其他注释
变量名选择不当。例如,
item1
是什么?这是您正在评估的猜测,所以它应该被称为possible_guess
?我怀疑你上面的§1.3的错误部分是由于变量名选择不当造成的。有大量不必要的复制。所有的
[:]
都是没有意义的,可以删除。变量List1
也是没有意义的(为什么不直接赋值给optionList
?),正如nextGuess
(它不仅仅分配给guess
?)您构建了
dummyList
,它包含了所有可能的秘密,这些秘密将与最后一个猜测相匹配,但是您将丢弃dummyList
中不在optionList
中的所有条目。那么为什么不直接循环optionList
并保留匹配的条目呢?像这样:您将建立一个表}在列表中(bull,cow)对和它们的索引之间来回映射。在
HMList
,该表统计每种公牛和奶牛的出现次数。您已经注意到有14个可能的(bull,cow)对,因此您编写了函数Adjustment
和{如果采用数据驱动方法并使用内置的^{} 方法,这些函数的实现可能会简单得多:
但在修正了上面的§1.3错误之后,您就不再需要} 而不是列表中,则可以避免{}。所以不是:
AdjustmentInverse
。如果将计数保存在^{你可以简单地写下:
3。改进的eh3代码>
使用标准库中的类^{} 可以将计算猜测(您的函数
HowManyBc
)简化为三行。在我碰巧更喜欢用字母来表示策划者的代码。
ACDB
比[0, 2, 3, 1]
好得多。但是我的evaluate
函数对于如何表示代码和猜测是灵活的,只要您将它们表示为可比较项的序列,因此如果您愿意,可以使用数字列表。在还请注意,我编写了一些doctests:这些是同时在文档中提供示例和测试函数的快速方法。
函数^{} 提供了一种方便的方法来构建代码列表,而不必编写四个嵌套循环:
Knuth的五猜测算法使用minimax principle。{a8}为什么不通过调用^来实现^ a8}?在
下面是一个运行示例:
相关问题 更多 >
编程相关推荐