How to solve the “Mastermind” guessing game?

后端 未结 10 423
有刺的猬
有刺的猬 2020-12-04 07:42

How would you create an algorithm to solve the following puzzle, \"Mastermind\"?

Your opponent has chosen four different colours from a set of six (yellow, blue, gre

相关标签:
10条回答
  • 2020-12-04 08:36

    Here's a link to pure Python solver for Mastermind(tm): http://code.activestate.com/recipes/496907-mastermind-style-code-breaking/ It has a simple version, a way to experiment with various guessing strategies, performance measurement, and an optional C accelerator.

    The core of the recipe is short and sweet:

    import random
    from itertools import izip, imap
    
    digits = 4
    fmt = '%0' + str(digits) + 'd'
    searchspace = tuple([tuple(map(int,fmt % i)) for i in range(0,10**digits)])
    
    def compare(a, b, imap=imap, sum=sum, izip=izip, min=min):
        count1 = [0] * 10
        count2 = [0] * 10
        strikes = 0
        for dig1, dig2 in izip(a,b):
            if dig1 == dig2:
                strikes += 1
            count1[dig1] += 1
            count2[dig2] += 1
        balls = sum(imap(min, count1, count2)) - strikes
        return (strikes, balls)
    
    def rungame(target, strategy, verbose=True, maxtries=15):
        possibles = list(searchspace)
        for i in xrange(maxtries):
            g = strategy(i, possibles)
            if verbose:
                print "Out of %7d possibilities.  I'll guess %r" % (len(possibles), g),
            score = compare(g, target)
            if verbose:
                print ' ---> ', score
            if score[0] == digits:
                if verbose:
                    print "That's it.  After %d tries, I won." % (i+1,)
                break
            possibles = [n for n in possibles if compare(g, n) == score]
        return i+1
    
    def strategy_allrand(i, possibles):
        return random.choice(possibles)
    
    if __name__ == '__main__':
        hidden_code = random.choice(searchspace)
        rungame(hidden_code, strategy_allrand)
    

    Here is what the output looks like:

    Out of   10000 possibilities.  I'll guess (6, 4, 0, 9)  --->  (1, 0)
    Out of    1372 possibilities.  I'll guess (7, 4, 5, 8)  --->  (1, 1)
    Out of     204 possibilities.  I'll guess (1, 4, 2, 7)  --->  (2, 1)
    Out of      11 possibilities.  I'll guess (1, 4, 7, 1)  --->  (3, 0)
    Out of       2 possibilities.  I'll guess (1, 4, 7, 4)  --->  (4, 0)
    That's it.  After 5 tries, I won.
    
    0 讨论(0)
  • 2020-12-04 08:39

    My friend was considering relatively simple case - 8 colors, no repeats, no blanks.

    With no repeats, there's no need for the max entropy consideration, all guesses have the same entropy and first or random guessing all work fine.

    Here's the full code to solve that variant:

    # SET UP
    import random
    import itertools
    colors = ('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'ultra')
    
    # ONE FUNCTION REQUIRED
    def EvaluateCode(guess, secret_code):
        key = []
        for i in range(0, 4):
            for j in range(0, 4):
                if guess[i] == secret_code[j]:
                    key += ['black'] if i == j else ['white']    
        return key
    
    # MAIN CODE
    # choose secret code
    secret_code = random.sample(colors, 4)
    print ('(shh - secret code is: ', secret_code, ')\n', sep='')
    # create the full list of permutations
    full_code_list = list(itertools.permutations(colors, 4))
    N_guess = 0
    while True:
        N_guess += 1
        print ('Attempt #', N_guess, '\n-----------', sep='')
        # make a random guess
        guess = random.choice(full_code_list)
        print ('guess:', guess)
        # evaluate the guess and get the key
        key = EvaluateCode(guess, secret_code)
        print ('key:', key)
        if key == ['black', 'black', 'black', 'black']:
            break
        # remove codes from the code list that don't match the key
        full_code_list2 = []
        for i in range(0, len(full_code_list)):
            if EvaluateCode(guess, full_code_list[i]) == key:
                full_code_list2 += [full_code_list[i]]
        full_code_list = full_code_list2
        print ('N remaining: ', len(full_code_list), '\n', full_code_list, '\n', sep='')
    print ('\nMATCH after', N_guess, 'guesses\n')
    
    0 讨论(0)
  • 2020-12-04 08:41

    Have you seem Raymond Hettingers attempt? They certainly match up to some of your requirements.

    I wonder how his solutions compares to yours.

    0 讨论(0)
  • 2020-12-04 08:45

    There is a great site about MasterMind strategy here. The author starts off with very simple MasterMind problems (using numbers rather than letters, and ignoring order and repetition) and gradually builds up to a full MasterMind problem (using colours, which can be repeated, in any order, even with the possibility of errors in the clues).

    The seven tutorials that are presented are as follows:

    • Tutorial 1 - The simplest game setting (no errors, fixed order, no repetition)
    • Tutorial 2 - Code may contain blank spaces (no errors, fixed order, no repetition)
    • Tutorial 3 - Hints may contain errors (fixed order, no repetition)
    • Tutorial 4 - Game started from the middle (no errors, fixed order, no repetition)
    • Tutorial 5 - Digits / colours may be repeated (no errors, fixed order, each colour repeated at most 4 times)
    • Tutorial 6 - Digits / colours arranged in random order (no errors, random order, no repetition)
    • Tutorial 7 - Putting it all together (no errors, random order, each colour repeated at most 4 times)
    0 讨论(0)
提交回复
热议问题