299. 猜数字游戏
中等
你在和朋友一起玩猜数字(Bulls and Cows)游戏,该游戏规则如下:
写出一个秘密数字,并请朋友猜这个数字是多少。朋友每猜测一次,你就会给他一个包含下述信息的提示:
1、猜测数字中有多少位属于数字和确切位置都猜对了(称为 "Bulls",公牛),
2、有多少位属于数字猜对了但是位置不对(称为 "Cows",奶牛)。也就是说,这次猜测中有多少位非公牛数字可以通过重新排列转换成公牛数字。
给你一个秘密数字secret和朋友猜测的数字guess,请你返回对朋友这次猜测的提示。
提示的格式为"xAyB",x是公牛个数,y是奶牛个数,A表示公牛,B表示奶牛。
请注意秘密数字和朋友猜测的数字都可能含有重复数字。
示例 1:
输入:secret = "1807", guess = "7810"
输出:"1A3B"
示例 2:
输入:secret = "1123", guess = "0111"
输出:"1A1B"
注意,两个不匹配的 1 中,只有一个会算作奶牛(数字猜对位置不对)。通过重新排列非公牛数字,其中仅有一个 1 可以成为公牛数字。
提示:
1 <= secret.length, guess.length <= 1000
secret.length == guess.length
secret 和 guess 仅由数字组成
问题分析:
这个猜数字游戏很有趣,有趣在每一次猜数字之后产生的提示信息,跟一般猜数字游戏给出的提示信息不一样,也正是因为这个不一样,才让人想一解为快。
在secret和guess中,不管是公牛bulls还是母牛cows,必然是secret和guess中都有的数字,所以我们要找出在secret和guess中有哪些公共数字,且统计出这些公共数字出现的次数,为此设计了tjshare(s1,s2)和tjnum(s1,s2)函数,tjshare(s1,s2)函数统计在s1和s2中有哪些公共数字,返回一个包含公共数字的列表,tjnum(s1,s2)统计s1和s2中公共数字出现的次数,返回两个字典。
为统计secret和guess中公牛bulls的数量,为此设计了函数bulls(s1,s2),将公牛数量以字典的形式返回。
公牛的数量可以用bulls(s1,s2)函数求出,那么如何求出母牛cows的数量呢?
最后通过countbullscows(s1,s2)函数实现,母牛的数量等于公共字符数量减去公牛的数量,即可得到。
程序如下:
#统计公共数字
def tjshare(s1,s2):
s1=set(s1)
s2=set(s2)
s=s1&s2
return list(s)
#统计公共数字的在s1和s2中的数量
def tjnum(s1,s2):
s=tjshare(s1,s2)
s1nums=dict()
s2nums=dict()
for i in s:
s1nums[i]=s1.count(i)
s2nums[i]=s2.count(i)
return s1nums,s2nums
#统计公牛的数量
def bulls(s1,s2):
s=[]
n=len(s1)
for i in range(n):
if s1[i]==s2[i]:
s.append(s1[i])
m=set(s)
b=dict()
for i in m:
b[i]=s.count(i)
return b
#统计公牛和母牛的数量,生成提示信息
def countbullscows(s1,s2):
s1num,s2num=tjnum(s1,s2)
s=bulls(s1,s2)
for i in s.keys():
s1num[i]=min(s1num[i],s2num[i])-s[i]
m=sum(s[i] for i in s.keys())
n=sum(s1num[i] for i in s1num.keys())
return str(m)+'A'+str(n)+'B'
#输入
secret=input('pls input secret=')
guess=input('pls input guess=')
#输出
print(countbullscows(secret,guess))
运行实例一:
pls input secret=12345
pls input guess=12453
2A3B
运行实例二:
pls input secret=111211
pls input guess=113416
3A0B
运行实例三:
pls input secret=121311
pls input guess=112346
2A2B
感悟:“三天不拿针,手就有点生。” 编程也是如此,常常思考并努力实践,定会得心应手。