1

私は初心者のプログラマーです。

私は課題の 6 推測アルゴリズムでマスターマインド ソルバーにコードを書いてきました。

(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 回の推測が可能であるため、問題ありません。利用可能な推測が 6 つしかない場合は、より賢いアプローチが必要になります。次の代替アルゴリズムは、先読みの 1 回の動きに基づいて最良の推測を行い、多くても 6 回の推測が必要です。(ただし、実行速度は非常に遅いです!) 繰り返しますが、これがどのように機能するかを調べるのは興味深いかもしれません (ヒント: maxima のリストの最小値を取ります)。

    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 の 5 回推測アルゴリズムです(実行速度はさらに遅くなります)。

    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 に答える