公牛与公牛Python中的奶牛(mastermind)。应该比较容易

时间:2013-11-15 17:22:36

标签: python algorithm

我是python的新手,我需要写一个“公牛和牛”游戏(a.k.a Mastermind) 它是这样的:

您首先获得2个输入; 1表示秘密的长度(可以是4-6),第2表示基数(可以是6-10)。 你可以假设秘密和猜测都有给定的长度(你不需要确定) 稍后,您还有另外2个输入。 1表示秘密(由空格分隔的数字链),第2表示基数(由空格分隔的数字链)。 如果秘密的数字等于或超过基数,程序将输出ERROR并退出。

澄清的一个例子:

5 (First input, length should be 5)
8 (The base. It means that no number is allowed to be 8 or beyond. You are only allowed to use 0,1,2,3,4,5,6,7)
1 2 7 2 5 (this is the secret)
7 2 2 1 1 (this is the guess)

输出:

1 BULLS 3 COWS

另一个例子:

6
9
0 0 0 0 0 6
8 22 2 2 1 4

输出:

0 BULLS 0 COWS

好的,所以我开始编写代码,我不确定到底应该使用什么,所以到目前为止我这样做了:

#get the length of the guess - an int number  between 4(included) to 6(included)
secretL = input()
#get the base of the guess - an int number  between 6(included) to 10(included)
secretB = input()
#get the guess
secret = raw_input()
secretsNumbers = map(int, secret.split())
#turn the chain into a singular INT number in order to make sure each of its digits does not equal or exceeds base, using %10
secretsNumbersMerge = int(''.join(map(str,secretsNumbers)))
newSecretsNumbersMerge = secretsNumbersMerge
while newSecretsNumbersMerge!= 0:
    checker = newSecretsNumbersMerge%10
    if checker<secretBase:
        newSecretsNumbersMerge = newSecretsNumbersMerge/10
    else:
        print ("ERROR")
        quit()

guess = raw_input()
guessNumbers = map(int, guess.split())

到目前为止一切都很好。这确实可以确保秘密符合基本要求。现在,我正处于检查公牛和奶牛的主要位置,我不太确定如何从这一点开始。

我的想法是首先检查公牛然后将它们移除(因此它不会与奶牛混在一起),然后检查奶牛但是是的......我很无能为力。

我甚至不确定在Python中使用什么。

提前致谢!

1 个答案:

答案 0 :(得分:1)

这是您的代码,但请尝试理解它的每一行:

import re
from collections import Counter

#get the length of the guess - an int number  between 4(included) to 6(included)
secretL = input()
#get the base of the guess - an int number  between 6(included) to 10(included)
secretB = input()
#get the guess
secret = raw_input()

# Check if the secret input uses a digit greater than the base value
# You can use the check on the next line as well. It can be made faster
# too by using search in place of findall.
# if len(re.findall(r"[^0-" + str(secretB) + r" ]+", secret)):
if sum((i!=" " and int(i) > secretB) for i in secret) > 0:
  print("Error")
  quit()

secretNumbers = map(int, secret.split())
guess = raw_input()
guessNumbers = map(int, guess.split())

# Count the bulls by iterating over the two lists simultaneously
bulls = sum(i==j for i, j in zip(secretNumbers, guessNumbers))

# Remove the bulls before counting the cows
secretNumbers, guessNumbers = zip(*((x,y) for x,y in zip(secretNumbers, guessNumbers) if x!=y))

# Cows are defined as the elements present in both the guess and the secret
# but not in the right position.
# If we ignore duplicates, this is the way to go about it.
cows = len(set(secretNumbers) & set(guessNumbers))

## If we count [1,1,2,4] and [5,3,1,1] to have 2 cows, this is how it should be:
#counter = Counter(secretNumbers) & Counter(guessNumbers)
#cows = sum(counter.itervalues())

print(str(bulls) + " BULLS " + str(cows) + " COWS")

如果有什么不清楚,请告诉我,我会补充说明。

另外,我不知道策划者的规则,并从你的描述中推断出它们。我不清楚第二个例子你是如何得到0头奶牛的。

更新1

  

if sum(i > secretB for i in secretNumbers) > 0:它是如何运作的?

请使用反引号(`)在评论,问题或答案中引用一小段代码。现在,让我们将这些代码分解为易于理解的部分:

  1. 考虑列表理解[ i > secretB for i in secretNumbers]。这将生成一个布尔列表。因此,如果您的基数为6且secretNumbers为[1,2,7,2,5],则会返回[False, False, True, False, False]。 (根据你的评论,这不是解释规则的方式,但我很确定你可以将这个条件修改为你需要的。)
  2. sum()是Python中非常有用的标准内置函数,它返回传递给它的任何iterable的总和。因此,sum([1,2,3,4])将返回10.
  3. 仍然要回答对布尔值列表求和的意义。以这种方式将True添加到True可能最初看起来很奇怪,但我认为它不是单声道的;毕竟,自2.3以来所有版本中bool is a subclass int
  4. _

    >>>issubclass(bool, int)
    True
    

    所以,你去了:sum(i > secretB for i in secretNumbers)告诉你输入中有多少数字超过基数。

    更新2:

    在OP澄清之后,Update 1的解释不再适用于正在讨论的代码,尽管OP现在理解使用列表推导来执行强大功能的一般技术。

    此外,澄清了计算COWS的条件,现在代码列出了两种方法 - 一种方法,而忽略了重复;第二,计算每个重复的实例。