1

我是一个初级程序员。

我一直在使用六猜算法的主脑求解器编写代码以进行分配。

(有关 mastermind 及其算法的更多信息:Mastermind on wiki

我几天前就想通了。但是我们的教授设置了固定的模板,然后我不知道如何将我的代码转换成它。

下面是我的代码。可能很尴尬,但它有效,而且速度并不慢。


def product(*args, repeat=1):
    pools = [list(pool) for pool in args] * repeat
    result = [[]]
    for pool in pools:
        result = [x+[y] for x in result for y in pool]
    for prod in result:
        yield list(prod)

def sort_list(total_list):
    d0=list()
    d1=list()
    d2=list()
    d3=list()
    d4=list()

    for x in total_list:
        mlist=list()
        alist = x
        n = 0
        while n<4:
            m = alist.count(alist[n])
            mlist.append(m)
            n = n + 1
        if max(mlist)==1:
            d0.append(alist)
        elif max(mlist)==2 and mlist.count(2)==2:
            d1.append(alist)
        elif max(mlist)==2 and mlist.count(2)>2:
            d2.append(alist)
        elif max(mlist)==3 :
            d3.append(alist)
        elif max(mlist)==4 :
            d4.append(alist)

    total_list = d0+d1+d2+d3+d4
    possible = [''.join(p) for p in total_list]
    return total_list

def computeFeedback(code,guess):    
    b = 0
    w = 0
    inCodeCount = {'A':0,'B':0,'C':0,'D':0, 'E':0, 'F':0}
    inGuessCount = {'A':0,'B':0,'C':0,'D':0, 'E':0, 'F':0}
    for i in range(0,4):
        if code[i] == guess[i]:
            b += 1
        inCodeCount[code[i]]+=1
        inGuessCount[guess[i]]+=1
    for ch in inCodeCount:
        w+=min(inCodeCount [ch], inGuessCount [ch])
    w-=b 
    feedback = str(w)+'w'+str(b)+'b'
    return feedback

guesscount=0
code=input()
while guesscount<8:
    guesscount += 1
    if guesscount==1:
        guess='ABCD'
        print("My guess is:",guess)
        feedback=computeFeedback(code,guess)
        if feedback!='0w4b':
            combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
            overlap=list()
            for x in combinations:
                fb=computeFeedback(guess,x)
                overlap.append(x)
                if fb != feedback:
                    overlap.pop()
            common=overlap
            overlap=list()

        else:
            print("Game Over in", guesscount,"steps")
            break
    if guesscount==2:
        guess='BCDE'
        print("My guess is:",guess)
        feedback=computeFeedback(code,guess)
        if feedback!='0w4b':
            combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
            overlap=list()
            for x in combinations:
                fb=computeFeedback(guess,x)
                overlap.append(x)
                if fb != feedback:
                    overlap.pop()
            common=[token for token in overlap if token in common]
            overlap=list()

        else:
            print('Game Over in,', guesscount,'steps')
            break
    if guesscount==3:
        guess='CDEF'
        print("My guess is:",guess)
        feedback=computeFeedback(code,guess)
        if feedback!='0w4b':
            combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
            overlap=list()
            for x in combinations:
                fb=computeFeedback(guess,x)
                overlap.append(x)
                if fb != feedback:
                    overlap.pop()
            common=[token for token in overlap if token in common]

            overlap=list()
        else:
            print('Game Over in', guesscount,'steps')
            break
    if guesscount==4:
        if common[0]=="acfb".upper():
            guess="dcad".upper()
        if common[0]=="aebf".upper():
            guess="edfd".upper()
        if common[0]=='AEFB':
            guess='EACC'
        if common[0]=='AFBE':
            guess='BFCD'
        if common[0]=='BAFE':
            guess='EADC'
        if common[0]=='BEAF':
            guess='EDAE'
        if common[0]=='BEFA':
            guess='EEDA'
        if common[0]=='EABF':
            guess='FDFB'
        if common[0]=='AADB':
            guess='BABD'
        if common[0]=='ABAE':
            guess='BBCC'
        if common[0]=='AEAF':
            guess='CFFD'
        if common[0]=='CAFA':
            guess='FDFA'
        if common[0]=='AAEE':
            guess='DDDF'
        else:
            guess=common[0]
        print("My guess is:",guess)
        if len(common)>1:
            common.pop(0)

            feedback=computeFeedback(code,guess)
            if feedback!='0w4b':
                combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
                overlap=list()
                for x in combinations:
                    fb=computeFeedback(guess,x)
                    overlap.append(x)
                    if fb != feedback:
                        overlap.pop()
                common=[token for token in overlap if token in common]
                overlap=list()
            else:
                print('Game Over in', guesscount,'steps')
                break
        else:
            print('Game Over in', guesscount,'steps') 
            break
    if guesscount==5:
        guess=common[0]
        print("My guess is:",guess)
        if len(common)>1:
            common.pop(0)

            feedback=computeFeedback(code,guess)
            if feedback!='0w4b':
                combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
                overlap=list()
                for x in combinations:
                    fb=computeFeedback(guess,x)
                    overlap.append(x)
                    if fb != feedback:
                        overlap.pop()
                common=[token for token in overlap if token in common]

                overlap=list()
            else:
                print('Game Over in', guesscount,'steps')
                break
        else:
            print('Game Over in', guesscount,'steps')
            break
    if guesscount==6:
            guess=common[0]
            print("My guess is:",guess)
            if len(common)>1:
                common.pop(0)

                feedback=computeFeedback(code,guess)
                if feedback!='0w4b':
                    combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
                    overlap=list()
                    for x in combinations:
                        fb=computeFeedback(guess,x)
                        overlap.append(x)
                        if fb != feedback:
                            overlap.pop()
                    common=[token for token in overlap if token in common]

                    overlap=list()
                else:
                    print('Game Over in', guesscount,'steps')
                    break
            else:
                print('Game Over in', guesscount,'steps')
                break
    if guesscount==7:
            guess=common[0]
            print("My guess is:",guess)
            if len(common)>1:
                common.pop(0)
                feedback=computeFeedback(code,guess)
                if feedback!='0w4b':
                    combinations=sort_list([''.join(x) for x in product('ABCDEF',repeat=4)])
                    overlap=list()
                    for x in combinations:
                        fb=computeFeedback(guess,x)
                        overlap.append(x)
                        if fb != feedback:
                            overlap.pop()
                    common=[token for token in overlap if token in common]

                    overlap=list()
                else:
                    print('Game Over in', guesscount,'steps')
                    break
            else:
                print('Game Over in', guesscount,'steps')
                break
if guesscount==8:
    print('Failure')

是的,这里有我必须完成的代码破解功能和运行该功能的策划引擎的模板:


模板

class CodeBreaker:
    def __init__(self):



    def makeGuess(self):

        return guess

    def getFeedback(self, feedbackStr):

引擎

from mastermind import CodeBreaker

def computeFeedback(code,guess):
    # Given a code and guess computes the feedback string

    b = 0
    w = 0
    inCodeCount = {'A':0,'B':0,'C':0,'D':0, 'E':0, 'F':0}
    inGuessCount = {'A':0,'B':0,'C':0,'D':0, 'E':0, 'F':0}
    for i in range(0,4):
        if code[i] == guess [i]:
            b += 1
        inCodeCount[code[i]] += 1
        inGuessCount[guess[i]] += 1
    for ch in inCodeCount:
        w += min(inCodeCount [ch], inGuessCount [ch])
    w -= b 
    feedback = str(w)+'w'+str(b)+'b'
    return feedback

code = input()

while (code != None):
    guesscount = 0
    myBreaker = CodeBreaker()
    while (guesscount < 8):
        guess = myBreaker.makeGuess()
        print("My guess is:",guess)
        guesscount += 1
        feedback = computeFeedback(code, guess)
        print(feedback)
        if feedback == "0w4b":
            print("Game Over in", guesscount,"steps")
            break
        myBreaker.getFeedback(feedback)
    if guesscount == 8:
        print("Failed to find the solution in 8 steps")
    code = input()

我上课不好。我什至不知道init应该包含什么。任何人都可以帮忙吗?

非常感谢!

4

1 回答 1

1

将代码转换为类的最简单方法是将所有代码放入getFeedback方法中,除了计算您发送给评估的猜测之外,记住属性中的猜测self.guess,并在下次makeGuess函数时返回叫。您还需要将所有全局变量(如common)转换为属性(如self.common)。这是一个草图:

class CodeBreaker:
    def __init__(self):
        self.guess_count = 0
        self.guess = 'ABCD'
        self.common = []

    def makeGuess(self):
        return self.guess

    def getFeedback(self, feedback):
        self.guess_count += 1
        if self.guess_count == 1:
            # ... your code here ...
            self.guess = 'BCDE'
        elif self.guess_count == 2:
            # ... your code here ...
            self.guess = 'CDEF'
        elif self.guess_count == 3:
            # ... your code here ...
        # ... and so on ...

我应该补充一点,您的代码非常重复。以下更改将是值得的:

  1. Python 标准库已经包含一个函数itertools.product来完成你的函数的工作product(尽管它以不同的方式获取它的参数),所以你最好使用它。

  2. 您为每个猜测复制基本上相同的代码(生成组合集,根据最近的猜测评估组合,更新common等等)。将此代码放入方法中应该很简单,这样您就不必多次复制它。

  3. 猜测 4 和更高的代码几乎相同:当然根本不需要复制此代码(只需同时编写if guesscount >= 4:和处理它们)。

您可能想研究这个类(它使用与您的解决方案类似的方法,但删除了所有重复),看看您是否能弄清楚它是如何工作的:

from itertools import product
from random import choice
from copy import copy

class CodeBreaker(object):
    all_codes = [''.join(c) for c in product(*['ABCDEF'] * 4)]

    def __init__(self):
        self.codes = copy(self.all_codes)
        self.guess = 'AABB'     # Best first guess!

    def makeGuess(self):
        return self.guess

    def getFeedback(self, feedback):
        self.codes = [c for c in self.codes if computeFeedback(c, self.guess) == feedback]
        self.guess = choice(self.codes)

在最坏的情况下,该算法最多可以进行 8 次猜测,但您有 8 次猜测可用,所以没关系。如果您只有六个可用的猜测,那么您需要一个更聪明的方法。以下替代算法基于一次前瞻做出最佳猜测,最多需要六次猜测。(但是,它运行得非常慢!)同样,您可能会发现研究它的工作原理很有趣(提示:它需要最大值列表中的最小值)。

    def getFeedback(self, feedback):
        self.codes = [c for c in self.codes if computeFeedback(c, self.guess) == feedback]
        def key(g): return max(Counter(computeFeedback(c, g) for c in self.codes).values())
        self.guess = min(self.codes, key = key)

这是Knuth 的五猜算法(运行速度更慢):

    def getFeedback(self, feedback):
        self.codes = [c for c in self.codes if computeFeedback(c, self.guess) == feedback]
        if len(self.codes) == 1:
            self.guess = self.codes[0]
        else:
            def key(g): return max(Counter(computeFeedback(c, g) for c in self.codes).values())
            self.guess = min(self.all_codes, key = key)

PS你教授的代码也不完美!除了不遵循传统的 Python 风格(参见PEP8)之外,它似乎也相当复杂和冗长。为什么不利用 Python 的collections.Counter类来写一些简短而简单的东西:

from collections import Counter

def computeFeedback(code, guess):
    """
    Return the string `{white}w{black}b` where `black` is a count of the
    characters in `guess` that appear at the same position in `code`
    and `white` is a count of the characters in `guess` that appear at
    a different position in `code`.

    >>> computeFeedback('ABCD', 'ACAD')
    '1w2b'
    >>> computeFeedback('ABAB', 'AABB')
    '2w2b'
    >>> computeFeedback('ABCD', 'DCBA')
    '4w0b'
    """
    w = sum((Counter(code) & Counter(guess)).values())
    b = sum(c == g for c, g in zip(code, guess))
    return '{}w{}b'.format(w - b, b)
于 2012-10-01T14:39:13.537 回答