在与python相关的面试中,很经常能看到这样类似的一道题:
有13只猴子围成一圈,编号分别为1~13,从1开始报数,报到10之后,下一个猴子又重新由1报起,每逢报到7的猴子出局,请设计程序,求得最终留下来的那一只猴子的编号。
以前,我的解法是老老实实地写几个循环嵌套,不过其实有更加省事的办法:使用字典!
以字典的键(int类型的1-13)作为猴子的编号,以他们对应的键值作为猴子当前的状态(报到几号数或者是已出局),定义字典的时候可以设置一个初值给它们。然后,设报数号为1,通过轮巡1-13号猴子进行报数,已出局的猴子跳过,未出局的猴子报数,报完判断当前猴子报的是否为7,是则将该猴子的状态设置为出局,然后报数号继续+1,到10之后又重置为1,猴子号数也是,报到13号猴子以后重置为1号猴子。最后通过判断是否已经有12只猴子出局,即可结束该循环。
代码如下:
monkey = {i + 1: "" for i in range(13)}
callnumber = 1
try:
while True:
for m in range(1, 14):
if monkey[m] != "out":
monkey[m] = callnumber
if callnumber == 7: monkey[m] = "out"
callnumber += 1
if callnumber > 10: callnumber = 1
if list(monkey.values()).count("out") == 12: raise TypeError
except:
[print("\nmonkey:{} is win".format(k)) for k, v in monkey.items() if v != "out"]
这里我还是用了两层循环,通过try...except加raise Error来一次性打破多重循环,实际上也可以做成一层循环,只做while True的就可以,里面的for循环可以自建一个循环计数器变量来替代掉。
也有使用列表的做法,当然,上一篇文章提到了高手通过极限缩减代码行数来秀技能,那在这个场景也是可以这样玩的
status = [[0 for i in range(13)], 1, 0]
while 1:
if status[0][status[2]] != -1:
status[0][status[2]] = status[1]
if status[1] == 7: status[0][status[2]] = -1
status[1] += 1
if status[1] > 10: status[1] = 1
if status[0].count(-1) == 12: break
status[2] += 1
if status[2] == len(status[0]): status[2] = 0
[print("monkey:{} is win".format(index + 1)) for index, k in enumerate(status[0]) if k != -1]
这段代码让人难受的地方在于,你要是不将status[0],status[1],status[2]替换成别的变量,你需要花费超级多的经历去看懂这段代码,玩儿嘛,哈哈哈!仅供参考,不喜勿喷~