POC百吉饼解算器

时间:2018-09-28 20:29:42

标签: python-3.x algorithm minimax

最近遇到Bagel Game之后,我的目标是弄清楚如何创建一个求解器,该求解器可以帮助某人明智地猜测所选择的数字。要创建求解器,必须熟悉游戏规则。它们如下:

  • 有一个秘密守护者(或“数字选择器”)和播放器(或“数字猜测器”)。
  • 秘密守护者( SK )和玩家( P )轮流互动。
  • SK 使用数字0-9创建一个数字。
  • 该数字中的任何一个数字都不能出现多次。
  • 因此,构造的数字中必须包含1到10位数字。
  • 一旦 SK 选择了一个数字, P 就会尝试猜测数字是什么。
  • SK 根据每次猜测将完全真实的信息返回给 P
  • P 猜出秘密或猜错太多次时,游戏结束。

SK 回答 P 的猜测时,答案始终是以下形式:

  • 如果猜测与秘密没有共同数字,则说“百吉饼”一次。
  • 对于每个与猜中和机密位置匹配的数字,“ Fermi”被说一次。
  • 对于猜中与秘密相同但与位置相同的每个数字,“ Pico”只说一次。
  • SK 的响应中,
  • P 不会按单词顺序接收其他信息。

根据上述规则,设计了以下概念验证程序:

#! /usr/bin/env python3
import itertools
import random
import sys


def main():
    digits = get_digits()
    all_possible = list(itertools.permutations(range(10), digits))
    while True:
        print('There are', len(all_possible), 'candidates.')
        if not all_possible:
            print('Someone must be confused ...')
            sys.exit()
        candidate = random.choice(all_possible)
        print('Try the number', ''.join(map(str, candidate)))
        pico, fermi, bagels = get_answer(digits)
        if bagels:
            for index, number in reversed(tuple(enumerate(all_possible))):
                if any(a == b for a, b in itertools.product(number, candidate)):
                    del all_possible[index]
        else:
            for index, number in reversed(tuple(enumerate(all_possible))):
                pico_test, fermi_test = test_number(number, candidate)
                if pico_test != pico or fermi_test != fermi:
                    del all_possible[index]
        assert candidate not in all_possible


def get_digits():
    while True:
        try:
            answer = int(input('How many digits are there in the number? '))
        except (EOFError, KeyboardInterrupt):
            sys.exit()
        except ValueError:
            print('Please enter a number.')
        else:
            if 1 <= answer <= 10:
                return answer
            print('Please enter a number between 1 and 10.')


def get_answer(digits):
    while True:
        try:
            answer = input('What answer was given? ')
        except (EOFError, KeyboardInterrupt):
            sys.exit()
        else:
            if not answer:
                print('Please tell me what was said.')
                continue
            pico = fermi = bagels = 0
            for word in answer.lower().split():
                if 'pico'.startswith(word):
                    pico += 1
                elif 'fermi'.startswith(word):
                    fermi += 1
                elif 'bagels'.startswith(word):
                    bagels += 1
                else:
                    print(f'Did not understand {word!r}')
                    break
            else:
                # input was accepted; now validate
                if pico + fermi + bagels == 0:
                    print('Please tell me what was said.')
                    continue
                if bagels > 0:
                    if bagels > 1:
                        print('There cannot be more than one bagel.')
                        continue
                    if pico or fermi:
                        print('Bagels cannot appear with pico or fermi.')
                        continue
                    return pico, fermi, bagels
                if fermi + pico > digits:
                    print('Pico and fermi cannot be more than digits.')
                    continue
                if fermi == digits:
                    print('Congratulations! We have won.')
                    sys.exit()
                return pico, fermi, bagels


def test_number(number, candidate):
    pico = fermi = 0
    for a, b in zip(number, candidate):
        if a == b:
            fermi += 1
        elif b in number:
            pico += 1
    return pico, fermi


if __name__ == '__main__':
    main()

如何修改此程序以将 min / max 搜索纳入其算法?

0 个答案:

没有答案