今天的开胃菜,让我们来模拟一个酒桌上的数字游戏——拍七:从1到100轮流报数,每逢含有7和7的倍数的人要拍一下手。
实现起来相当简单,会打字的人都会写。
for i in range(1,101):
if i%7==0 or '7' in str(i):
print('pass')
else:
print(i)
接下来,我们来模拟一次猜数字游戏,不过猜数的人不是我们,而是用折半查找的思想,看看多少次能猜对。我们知道,二分查找的最大次数是log(N),即int(log(N))+1,以N=300为例,最多为6次,。
import random
secret = random.randint(1,300)
high = 300
low=0
count=0
while 1:
guess = int((low+high)/2)
count+=1
if guess>secret:
high=guess
elif guess
最后,稍微提高一点难度,让我们求解九宫格(众所周知,三阶幻方的解法有8个)。
首先,我们用itertools模块里的permutations函数获得1-9中任取三个数的全排列;
接下来用三层循环和条件语句,暴力找到所有符合条件的组合:其中行或列的和是15,只要两行的和为15,剩下一行自然也是15,所以我们可以只写两个;
最后过滤掉重复矩阵:把第一行和第二行都放到集合里面,若断他们的交集长度为0,则表示他们没有交集;同理,定下两行自然也能定下第三行,所以不用再写。
下面是代码:
import itertools
import numpy as np
nums=[p for p in itertools.permutations(range(1,10),3) if sum(p)==15] #在全排列中取出所有和为15的组合
for row1_1,row1_2,row1_3 in nums:
for row2_1, row2_2, row2_3 in nums:
for row3_1, row3_2, row3_3 in nums:
if row1_1+row1_2+row1_3==15 \
and row2_1+row2_2+row2_3==15 \
and row1_1+row2_1+row3_1==15 \
and row1_2+row2_2+row3_2==15 \
and row1_1+row2_2+row3_3==15 \
and row1_3+row2_2+row3_1==15:
row1=row1_1,row1_2,row1_3
row2=row2_1,row2_2,row2_3
row3=row3_1,row3_2,row3_3
if len(set(row1)&set(row2))== 0:
matrix=[row1,row2,row3]
print(matrix)
进python群:835017344,获取python学习资料
虽然看起来时间复杂度是 ( ),但程序计算时间只需要0.1s。
有没有办法一行代码求解九宫格呢?当然可以,还是要用到itertools.permutations:
p=list(p for p in itertools.permutations(range(1,10),9) if sum([p[0],p[1],p[2]])==sum([p[3],p[4],p[5]])==15 \
and sum([p[0],p[3],p[6]])==sum([p[1],p[4],p[7]])==15 and sum([p[0],p[8]])==sum([p[2],p[6]]))
#print(p)
我们注意到最后一个判断条件是sum([p[0],p[8]])==sum([p[2],p[6]]),其实这也是对角线和为15的变体。在行、列都确定以后,让对角线端点的和相等,中心点的数值自然也定下来了。
但是,这条语句的运行时间是上段代码的5倍!其实两段程序的判断条件是一样的,区别就在于前一段代码先求的是1-9中任取三个数,这个过程要比求1-9的全排列快很多,也少很多(C(3,9)和9!),因此后面循环体的时间复杂度中的基数N远远小于1-9的全排列个数。