Python程序设计基础及实践(慕课版)
习题解答
第一章习题解答
1.请写出十进制数3732的二进制和十六进制表示形式。
解答:111010010100, E94
2.请写出十六进制数6dA8的十进制表示形式。
解答:66650
3.八进制数会是什么样的?请写出十进制数3732的八进制表示形式。
解答:八进制数由数字0-7构成。3732表示成八进制是 7224。
4.如何求一个十进制小数的K进制表示形式?
解答:K进制小数 0.A0A1……An的值是:
A0×K-1+A1×K-2+……+An×K-(n +1)
(0.12)10 = 1 ×10-1 + 2 ×10-2
(0.1)3 = 1×3-1 即1/3, 表示成10进制就是无限循环小数
小于1的十进制数的小数转K进制的方法是:每次将小数部分乘以K,记下乘积的整数部分(0也要记),乘积的小数部分继续乘以K,然后再记下乘积的整数部分……直到乘积的小数部分变成0,或者记录的整数部分达到要求的位数(有可能小数部分永远不会变成0)。最终记录下来的整数拼起来就是原小数的K进制表示形式的小数点后面的部分。
★5. 要用多少个字节才能表示汉字呢?请设计一种编码方案,使得这种编码方案能表示几千个常用汉字以及英文字母和阿拉伯数字。并且,要求只用一个字节表示数字、英文字母和标点符号,这样比较节省存储空间。
解答:常用的几千个汉字,每个汉字用2个字节就可以表示。国标汉字编码方案采用连续两个最高位(最左位)为1的字节来表示一个汉字,数字,英文字母和标点符号则依然沿用ASCII编码表示。
6.如何用一系列的比特来表示和存储视频和声音呢?
解答:视频是由每秒若干副(一般是24或30)的图像组成。图像是由像素组成。每个像素有红、绿、蓝三个分量,每个分量可以用一个整数表示,整数可以用一系列比特来表示,因此视频也可以用一系列比特表示。声音是由每秒钟若干个采样点(一般是数万、数十万个)的声波振幅表示的。振幅可以用一个整数表示,因此一秒的声音就可以用若干个整数来表示。
第二章习题解答
1.字符菱形(P005):输入一个字符,输出由该字符构成的字符菱形。
解答:
c = input()
print( ” ” + c)
print( ” ” + c + c + c)
print( c * 5)
print( ” ” + c*3)
print( ” ” * 2 + c)
2.输出第二个整数(P006):输入三个整数,输出第二个整数。
解答:
print(input().split()[1])
3.求三个数的和(P007):输入三个整数或小数,输出它们的和。
解答:
s = input().split()
print(float(s[0]) + float(s[1]) + float(s[2]))
4.字符串交换(P008):输入两个长度为4的字符串,交换这两个字符串的前两个字符后输出。
解答:
a = input()
b = input()
print( b[0] + b[1] + a[2] + a[3] )
print( a[0] + a[1] + b[2] + b[3] )
5.字符串中的整数求和(P009):输入两个长度为3的字符串,每个字符串前两个字符是数字,后一个字符是字母。 求这两个串中的整数的和。
解答:
解法1:
s = input().split()
a,b = s[0],s[1]
print(int(a[0]+a[1] ) + int(b[0] + b[1]))
解法2:
s = input().split()
print(int(s[0][0]+s[0][1] ) + int(s[1][0] + s[1][1]))
第三章习题解答
1.计算2的幂(P017):给定非负整数n,求2n。
解答:
n = int(input())
print(2**n)
2.计算多项式的值(P018):对于多项式f(x) = ax3+bx2+cx+d和给定的a, b, c, d, x,计算f(x)的值。
解答:
lst = input().split()
x,a,b,c,d = float(lst[0]),float(lst[1]),float(lst[2]),float(lst[3]),float(lst[4])
print( “%.7f” % (a*x**3 + b*x*x + c*x + d))
3.车牌限号(P019):今天某市交通管制,车牌尾号为奇数的车才能上路。问给定的车牌号今天是否能上路。
解答:
s = input()
if int(s[-1]) % 2:
print(“YES”)
else:
print(“NO”)
4.点和正方形的关系(P020):有一个正方形,四个角的坐标(x,y)分别是(1,-1),(1,1),(-1,-1),(-1,1),x是横轴,y是纵轴。写一个程序,判断一个给定的点是否在这个正方形内(包括正方形边界)。
解答:
s = input().split()
x = float(s[0])
y = float(s[1])
if x >= -1 and x <= 1 and y >=-1 and y <= 1:
print(“yes”)
else:
print(“no”)
5.计算邮资(P021):根据邮件的重量和用户是否选择加急计算邮费。计算规则:重量在1000克以内(包括1000克), 基本费8元。超过1000克的部分,每500克加收超重费4元,不足500克部分按500克计算;如果用户选择加急,多收5元。
解答:
t=input().split()
a=int(t[0])
b=t[1]
if a <= 1000:
cost = 8
else:
cost = 8 + ((a-1000)//500 + ((a-1000)%500 != 0))*4
if b == “y”:
cost += 5
print(cost)
6.分段函数(P022):编写程序,计算下列分段函数y=f(x)的值。
y=-x+2.5; 0 <= x < 5
y=2-1.5(x-3)(x-3); 5 <= x < 10
y=x/2-1.5; 10 <= x < 20
解答:
x = float(input())
if 0 <= x < 5:
print(“%.3f” % (-x + 2.5))
elif 5 <= x < 10:
print(“%.3f” % ( 2-1.5*(x-3)*(x-3)))
else:
print(“%.3f” % ( x/2 – 1.5 ))
7.大象喝水(P023):一只大象口渴了,要喝20升水才能解渴,但现在只有一个深h厘米,底面半径为r厘米的小圆桶(h和r都是整数)。问大象至少要喝多少桶水才会解渴。
解答:
lst = input().split()
h,r = int(lst[0]),int(lst[1])
v = 3.14159 * r * r * h /1000
if 20 / v > 20 // v:
print(int(20//v + 1)) # 如果x是小数,int(x)可以将其转成整数(去尾取整)
else:
print(“.0f” % 20//v) #这种方式也可以
8.苹果和虫子2(P024):你买了一箱n个苹果,很不幸的是买完时箱子里混进了一条虫子。虫子每x小时能吃掉一个苹果,假设虫子在吃完一个苹果之前不会吃另一个,那么经过y小时你还有多少个完整的苹果?
解答:
lst = input().split()
n,x,y = int(lst[0]),int(lst[1]),int(lst[2])
n -= (y //x ) + ( y%x != 0)
if n < 0:
n = 0
print(n)
★ 9.求一元二次方程的根(P025):输入方程ax2+bx+c=0的系数a、b、c,求其根。提示:注意避免输出-0.000这样的数。
解答:
import math
eps = 0.000001
lst = input().split()
a,b,c = float(lst[0]),float(lst[1]),float(lst[2])
if abs(b*b – 4 * a * c) < eps:
tmp = -b/(2*a)
if abs(tmp) < eps:
tmp = 0
print(“x1=x2=%.5f” % tmp)
elif b*b > 4 * a * c:
tmp = math.sqrt(b*b-4*a*c)
r1 = (-b+tmp)/(2*a)
r2 = (-b-tmp)/(2*a)
if abs(r1) < eps:
r1 = 0
if abs(r2) < eps:
r2 = 0
if r1 <= r2:
r1,r2 = r2,r1
print(“x1=%.5f;x2=%.5f” % (r1,r2))
else:
real = -b/(2*a)
if abs(real) < eps:
real = 0
imag = math.sqrt(4*a*c -b*b)/(2*a)
if abs(imag) < eps:
imag = 0
print(“x1=%.5f+%.5fi;x2=%.5f-%.5fi” % (real,imag,real,imag))
注意:
1) 由于计算机有误差,判断两个小数相等不能直接用 a == b形式,应该用 abs(a-b) < eps的形式,eps可以是一个很小的数,比如前面 让 eps = 0.000001 。abs表示求绝对值
总之,两个小数的差足够小了,就认为他们相等。这个足够小取多大,和具体题目相关,一般取10的-6次方就差不多
2) 要避免输出 -0.00000 ,避免办法是自己判断,如果要输出x,且发现 abs(x) < eps,则让 x = 0,然后再输出。计算机算小数有误差,一个数如果很接近0,我们就应该认为它是0。
不照上面的做,则
输入: 1 0 7.3 会产生 -0
输入:1.3225 2.3 1 ,本来应该是 b*b == 4 * a* c的,结果被判不是
第四章习题解答
1.求整数的和与均值(P040):读入n个整数,求它们的和与均值。
解答:
n = int(input())
sum = 0
s = input()
if ” ” in s: #或 len(s.split()) > 1
nums = s.split()
for i in range(n):
sum += int(nums[i])
else:
sum += int(s)
for i in range(n-1):
sum += int(input())
print(sum,’%.5f’%(sum/n))
2.整数序列的元素最大跨度值(P041):给定一个长度为n的非负整数序列,请计算序列的最大跨度值(最大跨度值 = 最大值减去最小值)。
解答:
n = int(input())
lst = input().split()
minX = maxX = int(lst[0]) #读入的第一个数当作当前最大值和最小值
for i in range(n-1):
x = int(lst[i+1])
minX = min(x,minX)
maxX = max(x,maxX)
print(maxX-minX)
3. 毕业生年薪统计(P042):告诉你一些毕业生的年薪,请计算其中年薪不少于30万的人数。
解答:
n = input()
s = map(int,input().split())
total = 0
for x in s:
if x >= 30:
total += 1
print(total)
4.奥运奖牌计数(P043):A国的运动员参与了n天的奥运比赛项目,已知该国每一天获得的金、银、铜牌数目。现在要统计一下A国所获得的金、银、铜牌数目及总奖牌数。
解答:
n = int(input())
gold = silver = bronze = 0
for i in range(n):
num = input().split()
gold += int(num[0])
silver += int(num[1])
bronze += int(num[2])
print(gold,silver,bronze,gold+silver+bronze)
5.鸡尾酒疗法(P044):现在要通过临床对照实验的方式验证各种新疗法是比鸡尾酒疗法疗效更好。假设鸡尾酒疗法的有效率为x,新疗法的有效率为y,如果y-x大于5%,则效果更好,如果x-y大于5%,则效果更差,否则称为效果差不多。给出n组临床对照实验的疗效数据,每组数据由病人数和痊愈人数两个整数构成,其中第一组采用鸡尾酒疗法,其他n-1组为各种不同的新疗法。请写程序判定各种新疗法效果相比鸡尾酒疗法如何。
解答:
n = int(input())
lst = input().split()
x = int(lst[1])/int(lst[0])
for i in range(n-1):
lst = input().split()
y = int(lst[1])/int(lst[0])
if y – x > 0.05:
print(“better”)
elif x – y > 0.05:
print(“worse”)
else:
print(“same”)
6.正常血压(P045):监护室每小时测量一次病人的血压,若收缩压在90 – 140之间并且舒张压在60 – 90之间(包含端点值)则称之为正常,现给出某病人若干次测量的血压值,计算病人保持正常血压的最长小时数。
解答:
n = int(input())
total = 0
maxTotal = 0
for i in range(n):
s = input().split()
high ,low = int(s[0]),int(s[1])
if 90 <= high <= 140 and 60 <= low <= 90:
total += 1
if total > maxTotal:
maxTotal = total
else:
total = 0
print(maxTotal)
7. 数字反转(P046):给定一个整数(可以是负的),请将该数各个位上数字反转得到一个新数。新数不得有多余的前导0。
解答:
解法一:数学解法
a = int(input())
b = abs(a) #取绝对值
c = 0
while b > 0:
#依靠除法和取模,依次取出b的个位数,十位数….加权累加到c上
c = c * 10 + (b % 10)
b //= 10
#此时c就是b的反转的结果
if a < 0:
print(-c)
else:
print(c)
解法二:纯字符串手工解法
s = input()
L = len(s)
t = “”
for i in range(L-1,-1,-1): #从后往前取出s的字符拼接起来
t += s[i]
i = 0
while t[i] == “0” and i < L-1:
#跳过前导0 ,但个位的那个0要保留。
i += 1
#此时t[i]不是”0″,或是个位的那个”0″
if s[0] == “-“: #输入是负数
print(“-” + t[i:-1]) # :-1是因为要把尾巴的负号去掉
else:
print(t[i:])
解法三:巧用 int 和字符串切片
#a[x:y:z]的意思,是从a[x]取到a[y](a[y]不算),每隔z个取一个,最后拼起来.z为负数代表倒着取
#x,y可以省略。x,y全省略表示从头取到尾或从尾取到头
s = input()
if “-” in s: #也可以 int(s) < 0, s[0] == “-“
s = “-” + s[-1:0:-1]
else:
s = s[::-1] #倒着从尾取到头
print(int(s))
8.求特殊自然数(P047):一个自然数,它的七进制与九进制表示形式都是三位数,且七进制与九进制的三位数顺序正好相反。求此自然数。
解答:
for i in range(81,343):
n = i
p70 = n % 7 #7进制个位数
n //= 7
p71 = n % 7 #7进制十位数
n//= 7
p72 = n % 7 #7进制百位数
if p70 * 81 + p71 * 9 + p72 == i:
print(i)
print(str(p72)+str(p71) + str(p70))
print(str(p70)+str(p71) + str(p72))
break
9.字符计数(P048):一个句子中有多个单词,单词之间可能有一个或多个空格。给定一个字符,请计算该字符在每个单词中的出现次数。
解答:
n = int(input())
for i in range(n):
c = input().lower()
s = input().split()
#tmp = “”
for x in s:
print(x.lower().count(c),end = ” “)
print(“”)
第五章习题解答
★★ 1.编写函数add,使得表达式
add(a1)(a2)……(an)()
返回值是a1+a2+……+an。提示:让add(x)返回一个闭包,该闭包接受的参数个数可变。
解答:
def add(x):
def g( *arg ):
if len(arg) == 0:
return x
else:
return add(x + arg[0])
return g
第六章习题解答
1.求最大公约数问题(P053):给定两个正整数,用辗转相除法求它们的最大公约数。
解答:
解法一,递归:
def gcd(a,b):
if a % b == 0:
return b
else:
return gcd(b,a%b)
lst = input().split()
a,b = int(lst[0]),int(lst[1])
print(gcd(a,b))
解法二,迭代
lst = input().split()
a,b = int(lst[0]),int(lst[1])
while a % b != 0:
a,b = b,a%b
print(b)
2.递归复习法(P054):学渣复习期末考试,要用递归复习法,即当他复习知识点k的时候,他发现理解知识点k必须先理解知识点k-1和知识点k-2,于是他先去学习知识点k-1和知识点k-2,当他复习知识点k-1的时候,又发现理解知识点k-1必须先理解知识点k-2与知识点k-3,又得先去复习知识点k-2和知识点k-3。已知复习每个知识点所需的时间,问要多少时间才能复习完知识点n。
解答:
def mytime(k):
if k < 3:
return k
return k + mytime(k-1) + mytime(k-2)
n = int(input())
for i in range(n):
k = int(input())
print(mytime(k))
3.多少种取法(P055):给定三个正整数m,n,s问从1到m这m个数里面取n个不同的数,使它们和是s,有多少种取法。
解答:
#m,n,s都会不断减少,要设置边界条件挡住,使得这三个变量不会一直减少到负无穷
#如果加上注释掉的部分,就能打出解
def ways(m,n,s):
#从1到m里面取n个不同的数,使其和为s,有多少种取法
#global result
if s == 0 and n == 0: #取0个数要求和为0,自然有1种取法,就是不取。
#print(result)
return 1
if m == 0 : #s和n有一个不为0,而已经没数可取,则无解。无解就是取法数为0
return 0
if n == 0: #如果s不为0,又不准取数,那就无解
return 0
else:
if m > s:
return ways(s,n,s)
else:
#result.append(m)
n1 = ways(m-1,n-1,s-m) #取m的做法
#del( result[len(result)-1])
return n1 + ways(m-1,n,s)
t = int(input())
for i in range (t):
lst = input().split()
m,n,s = int(lst[0]),int(lst[1]),int(lst[2])
print(ways(m,n,s))
4.很简单的整数划分问题(P074):求将正整数n表示成若干个正整数之和,有多少种不同方式。6=1+2+3和6=3+2+1算同一种方式。
解答:
def ways(m,n):
if m == 0:
return 1
if n == 0:
return 0
w = ways(m,n-1)
if m >= n:
w += ways(m-n,n)
return w
a = int(input())
print(ways(a,a))
5.奇异三角形:
一个边长为x的0阶奇异三角形,是一个边长为x的等边三角形。
一个边长为x的n阶奇异三角形,是一个边长为x的等边三角形,三个角上分别是一个边长为x/2的n-1阶奇异三角形。
下图从左到右分别是0阶、1阶和2阶奇异三角形:
输入整数 n(0<=n<=5),绘制n阶奇异三角形。
解答:
import turtle
def triangle(size,n): #size是长度,n是阶数目,以画笔当前位置作为左下角,画一个边长为size,阶为n的奇异三角形
if n == 0: #0阶则直接画一个三角形,以笔的当前位置作为左下角
turtle.pendown()
turtle.seth(60) #设置方向为60度
turtle.fd(size) #前进size像素
turtle.right(120) #右转120度
turtle.fd(size)
turtle.right(120)
turtle.fd(size)
turtle.penup()
else:
pos = turtle.pos()
triangle(size/2,n-1)
turtle.goto(pos)
turtle.seth(60)
turtle.fd(size/2)
triangle(size/2,n-1)
turtle.goto(pos)
turtle.seth(0)
turtle.fd(size/2)
triangle(size/2,n-1)
turtle.setup(800,800) #窗口缺省位于屏幕正中间
turtle.speed(-1000)
turtle.penup()
turtle.goto(-200,-200)
turtle.pensize(2)
level =4
triangle(300,level)
turtle.done() #保持绘图窗口
★ 6.分解因数(P056):给出一个正整数a,要求分解成若干个正整数的乘积,即a = a1 * a2 * a3 * … * an,并且1 < a1 <= a2 <= a3 <= … <= an,问这样的分解的种数有多少。注意到a = a也是一种分解。
解答:
def ways(m,n):
if m == n:
return 1
if m > n:
return 0
#n的分解方法,m是最小因子
for i in range(m,n+1):
if n % i == 0:
if n == i:
return 1
else:
return ways(i + 1,n) + ways(i,n//i)
n = int(input())
for i in range(n):
a = int(input())
print(ways(2,a))
★★ 7.全排列(P057):给定一个由不同的小写字母组成的字符串,输出这个字符串的所有全排列。 我们假设对于小写字母有’a’ < ‘b’ < … < ‘y’ < ‘z’,而且给定的字符串中的字母已经按照从小到大的顺序排列。(提示:和N皇后问题一样,要使用列表)
解答:
s = input()
lst = list(s)
lst.sort()
n = len(lst)
result = [0] * n
def permutation(i):
if i == n:
for x in result:
print(x,end=””)
print(“”)
return
for x in range(n):
ok = True
for y in range(i):
if result[y] == lst[x]:
ok = False
break
if ok:
result[i] = lst[x]
permutation(i+1)
permutation(0)
第七章习题解答
1.过滤多余的空格(P064):一个句子中也许有多个连续空格,过滤掉多余的空格,只留下一个空格。
解答:
s = input().split()
result = “”
for x in s:
result += x + ” “
print(result.strip())
2.统计数字字符个数(P065):输入一行字符,统计出其中数字字符的个数。
解答:
s = input()
total = 0
for x in s:
if x >= “0” and x <= “9”:
total += 1
print(total)
3.大小写字母互换(P066):把一个字符串中所有出现的大写字母都替换成小写字母,同时把小写字母替换成大写字母。
解答:
s = input()
for c in s:
if ‘a’ <= c <= ‘z’:
print(chr(ord(c) – 32 ),end=””)
elif ‘A’ <= c <= ‘Z’:
print(chr(ord(c) + 32),end=””)
else:
print(c,end=””)
4.找第一个只出现一次的字符(P067):给定一个只包含小写字母的字符串,请你找到第一个仅出现一次的字符。
解答:
解法1:
s = input()
for i in range(len(s)):
if s[i] not in s[i+1:] and s[i] not in s[:i]:
print(s[i])
exit() #exit结束整个程序
print(“no”)
解法2:
s=input()
for c in s:
if s.count(c)==1:
print(c)
break
else:print(“no”)
解法3:最快,比前两种快n倍,n是字符串字符数目
xxx=list(input())
lst=[0]*26 #lst[i]表示编码为ord(‘a’)+i的字符的出现次数
flag=1
for i in xxx:
lst[ord(i) – ord(‘a’)] +=1
for i in xxx:
if lst[ord(i)-ord(‘a’)]==1:
print(i)
exit()
print(“no”)
5.判断字符串是否为回文(P068):输入一个字符串,输出该字符串是否是回文串。回文串是指顺读和倒读都一样的字符串。比如:abba,cccdeedccc都是回文字符串。
解答:
s = input()
if s == s[::-1]:
print(“yes”)
else:
print(“no”)
6.字符串最大跨距(P069):有三个字符串S,S1,S2,想检测S1和S2是否同时在S中出现,且S1位于S2的左边,并S1和S2不重叠。计算满足上述条件的最右边的S2的起始点与最左边的S1的终止点之间的字符数目。
解答:
s,s1,s2 = input().split(“,”)
pos1 = s.find(s1)
pos2 = s.rfind(s2)
if pos1 == -1 or pos2 == -1:
print(-1)
exit()
if pos2 – pos1 >= len(s1):
print(pos2-(pos1+len(s1)))
else:
print(-1)
7.找出全部子串位置(P070):两个字符串s1,s2,找出s2在s1中所有出现的位置。
解答:
n = int(input())
for i in range(n):
s1,s2 = input().split()
found = False
start = 0
i = s1.find(s2,start)
while i != -1:
found = True
print(i,end = ” “)
start = i + len(s2)
i = s1.find(s2, start)
if not found:
print(“no”)
else:
print(“”)
8.石头剪刀布(P071):已知两人有不同的周期性出拳序列,比如一人总是“石头-布-石头-剪刀-石头-布-石头-剪刀……”循环。问出拳N次后,谁赢得多。
解答:
def Win(a,b):
if a == b:
return 0
if a == 0:
if b == 2:
return 1
else:
return -1
elif a == 2:
if b == 0:
return -1
else:
return 1
elif a == 5:
if b == 0:
return 1
else:
return -1
lst = input().split()
n ,na,nb = int(lst[0]),int(lst[1]),int(lst[2])
a = tuple(map(int,input().split()))
b = tuple(map(int,input().split()))
awin = 0
pa = 0
pb = 0
for i in range(n):
awin += Win(a[pa],b[pb])
pa = ( pa + 1 ) % na
pb = ( pb + 1 ) % nb
if awin == 0:
print(“draw”)
elif awin > 0:
print(“A”)
else:
print(“B”)
9.向量点积计算(P072):给定两个n维向量a=(a1,a2,…,an)和b=(b1,b2,…,bn),求点积a·b=a1b1+a2b2+…+anbn。
解答:
n = int(input())
a = tuple(map(int,input().split()))
b = tuple(map(int,input().split()))
total = 0
for i in range(n):
total += a[i] *b[i]
print(total)
10.万年历(P073):给定年月日,求星期几。已知2020年11月18日是星期三。本题不但有公元前年份,还有公元0年,这个和真实的纪年不一样。
解答:
def isLeapYear(n):
if n%4 ==0 and n%100!= 0 or n%400 == 0: #闰年
return True
return False
def yearDays(n):
if isLeapYear(n):
return 366;
return 365
monthDays = [-1,31,28,31,30,31,30,31,31,30,31,30,31]
def countWeekDay(year,month,date):
days = 0 #从2012-01-22开始过了多少天
if year >= 2012:
for y in range(2012,year):
days += yearDays(y)
if isLeapYear(year):
monthDays[2] = 29
else:
monthDays[2] = 28
for i in range(1,month):
days += monthDays[i]
days += date
days -= 22 #2012年1月22日是星期天
if days >= 0:
return days % 7
else:
return (7 + days) % 7
else:
for y in range(2011,year,-1):
days += yearDays(y)
if isLeapYear(year):
monthDays[2] = 29
else:
monthDays[2] = 28
for i in range(12,month,-1):
days+= monthDays[i]
days+= monthDays[month] – date
days += 22
return (7 – (days % 7)) % 7
weekDays = (“Sunday”,”Monday”,”Tuesday”,”Wednesday”,”Thursday”, “Friday”,”Saturday”)
n = int(input())
for i in range(n):
lst = input().split()
year,month,date = int(lst[0]),int(lst[1]),int(lst[2])
if isLeapYear(year):
monthDays[2] = 29
else:
monthDays[2] = 28
if month <1 or month > 12 or date < 1 or date > monthDays[month]:
print(“Illegal”)
else:
print(weekDays[countWeekDay(year,month,date)])
11. 成绩排序(P093):给出一些学生的姓名和成绩,将学生按成绩从高到低排序。成绩相同的学生,按照姓名从小到大排序。
解答:
n = int(input())
students = []
for i in range(n):
s = input().split()
students.append((s[0],int(s[1])))
students.sort(key = lambda x : (-x[1],x[0]))
for x in students:
print(x[0],x[1])
12.病人排队(P075):请将登记的病人按照以下原则排出看病的先后顺序:1)老年人(年龄 >= 60岁)比非老年人优先看病。2) 老年人按年龄从大到小的顺序看病,年龄相同的按登记的先后顺序排序。3)非老年人按登记的先后顺序看病。
解答:
def f(x):
if x[1] >= 60:
return (0,-x[1],x[2])
else:
return (1,0,x[2])
n = int(input())
p = []
for i in range(n):
s = input().split()
p.append((s[0],int(s[1]),i))
p.sort(key = f)
for i in range(n):
print(p[i][0])
13. 扑克牌排序(P094): 一副扑克牌有52张牌,分别是红桃,黑桃,方片,梅花各13张,不包含大小王,现在Alex抽到了n张牌,请将扑克牌按照牌面从大到小的顺序排序。
解答:
def f(card):
colors = ‘hsdc’
nums = [‘2’,”A”,”K”,”Q”,”J”]
for i in range(10,2,-1):
nums.append(str(i))
return (nums.index(card[1:]),colors.index(card[0]))
while True:
try:
s = input().split()
except:
break
s.sort(key=f)
for x in s:
print(x,end= ” “)
print(“”)
14.回文子串(P076):给定一个字符串,输出所有长度至少为2的回文子串。子串长度小的优先输出,若长度相等,则出现位置靠左的优先输出。
解答:
def isHw(s):
return s == s[::-1]
s = input()
L = len(s)
result = []
for i in range(L):
for j in range(i+1,L):
tmps = s[i:j+1]
if isHw(tmps):
result.append((j-i,i,tmps))
result.sort()
for x in result:
print(x[2])
15.矩阵乘法(P077):给定两个矩阵,计算其乘积。
解答:
n,m,k = map(int,input().split())
a = []
b = []
for i in range(n):
a.append(list(map(int,input().split())))
#a的每个元素都是一个列表,那么a就是一个二维列表,即矩阵
#a的每个元素相当于矩阵的一行
for i in range(m):
b.append(list(map(int,input().split())))
c = [[0 for j in range(k)] for i in range(n)]
#c是一个 3*3矩阵,所有元素都是0
for i in range(n):
for j in range(k): #计算c[i][j]
for kk in range(m):
c[i][j] += a[i][kk] * b[kk][j]
for i in range(n):
for j in range(k):
print(c[i][j],end = ” “) #行末多空格没关系
print(“”)
16.矩阵转置(P078):给定一个矩阵,求其转置矩阵。
解答:
s = input().split()
n , m = int(s[0]),int(s[1])
matrix = []
for i in range(n):
matrix.append(list(map(int,input().split())))
m2 = [ [0 for i in range(n)] for j in range(m)]
for i in range(m):
for j in range(n):
m2[i][j] = matrix[j][i]
for i in range(0,m):
for j in range(0,n):
print(m2[i][j],end = ” “)
print(“”)
17.计算鞍点(P079):寻找一个矩阵的鞍点。鞍点指的是矩阵中的一个元素,它是所在行的最大值,并且是所在列的最小值。
解答:
#本题目有的数据是25个数在同一行
#基本思路:如果第i行的最大值在第j列,而第j列的最小值也在第i行,那么(i,j)就是鞍点
#因此要求出每行的最大值在那一列,求出每一列的最小值在哪一行
MX = 5
m = []
maxJ = [0]*MX #maxJ[i]是第i行的最大值的列号
minI = [0]*MX #minI[j]是第j列的最小值的行号
for i in range(MX):
s = list(map(int,input().split()))
if len(s) > MX:
for k in range(MX):
m.append(s[k*MX:k*MX+MX])
break;
else:
m.append(s)
for i in range(MX):
for k in range(1,MX):
if m[i][k] > m[i][maxJ[i]]:
maxJ[i] = k
for i in range(MX):
for k in range(1,MX):
if m[k][i] < m[minI[i]][i]:
minI[i] = k
found = False
for i in range(MX):
if minI[maxJ[i]] == i: # 第i行最大值所在的列,其最小值所在的行正好是i,那么a[i][maxJ[i]]是鞍点
print(i+1, maxJ[i]+1, m[i][maxJ[i]])
found = True
break
if not found:
print(“not found”)
18.最简单的单词(P080):现有数量巨大的单词,每个人都对10个单词进行评难度分,不同的人可能对同一个单词评分,如果单词被多个人评分,它的综合评分是这些评分的平均数,求综合评分最小的单词。
解答:
T = int(input())
for t in range(T):
dt = dict([]) #元素 word:(3,89) 3人评分之和 89
n = int(input())
for i in range(10*n):
lst = input().split()
word = lst[0]
score = int(lst[1])
if word not in dt:
dt[word] = [1,score]
else:
dt[word][0] += 1 #人数
dt[word][1] += score #分数
minScore = None
for x in dt.items():
if minScore is None or minScore > x[1][1]/x[1][0]:
minScore = x[1][1]/x[1][0]
ans = x[0]
print(ans)
19.校园食宿预订系统(P081):某校园为方便学生订餐,推出食堂预定系统。食宿平台会在前一天提供菜单,学生在开饭时间前可订餐。 食堂每天会推出m个菜,每个菜有固定的菜价和总份数,售卖份数不能超过总份数。 假设共有n个学生点餐,每个学生固定点3个菜,当点的菜售罄时, 学生就买不到这个菜了。 请根据学生预定记录,给出食堂总的预定收入。
解答:
n,m = map(int,input().split())
dishes = {}
for i in range(m):
s = input().split()
dishes[s[0]] = [int(s[1]),int(s[2])]
total = 0
for i in range(n):
s = input().split()
for d in s:
if dishes[d][1] > 0:
dishes[d][1] -= 1
total += dishes[d][0]
print(total)
★ 20.更强的卷王查询系统(P082):“卷王”的定义是:给定一组课程,这组课程全部上过的学生中,这组课程平均分最高的学生。小明已经通过复杂的数据挖掘手段得到了要分析的课程组所有学生的成绩,现在需要你按照上述定义,对每组课程找出那个真正的“卷王”。学生有100,000人。
解答:
dictCourse = {}
#结构:{ “huaxue”:{“jack”,”jane”},”wuli”:{“mike”,”john”}}
dictStudent = {}
#结构:
#{“mike”:{“shuxue”:75,”wuli”:80},”jane”:{“shuxue”:71,”huaxue”:82}…}
eps = 1e-6
n = int(input())
for i in range(n):
course,name,score = input().split()
if course in dictCourse:
dictCourse[course].add(name)
else:
dictCourse[course] = {name}
if name in dictStudent:
dictStudent[name][course] = int(score)
else:
dictStudent[name] = {course:int(score)}
m = int(input())
for i in range(m):
s = input().split()
num = int(s[0])
s = s[1:]
st = set([])
for course in s:
if st == set([]):
st = dictCourse[course]
else:
#print(“dictCourse=”,course,dictCourse[course])
st = st & dictCourse[course]
#print(“st is: “, st)
maxScore = -100
kingName = “”
for stud in st:
total = 0
for course in s:
total += dictStudent[stud][course]
av = total / num
if av – maxScore > eps:
maxScore = av
kingName = stud
elif not maxScore – av > eps:
maxScore = av
if kingName == “”:
kingName = stud
else:
if kingName > stud:
kingName = stud
print(kingName)
第九章习题解答
1.有一个文本文件包含所有学生的学号和姓名,还有一个文本文件包含某次openjudge作业学生的提交排名记录。排名记录中包含学生的昵称和通过的题目数。昵称可能包含姓名,可能包含学号,也可能都包含。给定一个算分规则,请根据这两个文件生成一个学生分数的文件。本题详情及用到的两个文本文件请见配书资源包“第九章习题1.zip”。
解答:
import sys
f = open(“id.txt”,”r”,encoding=”utf-8″)
students = f.readlines()
f.close()
students.sort()
f = open(“finalscore.txt”,”r”,encoding=”utf-8″)
scores = f.readlines()
f.close()
f = open(sys.argv[1],”w”,encoding=”utf-8″)
for st in students:
st = st.strip()
if st == “”:
continue;
id,name = st.split(“\t”)
found= False
for sc in scores:
lst = sc.split(“\t”)
if id in lst[1] or name in lst[1]:
found = True
num = int(lst[3])
# 分数计算办法: 1题50,2题60,此后每做一题加4分
finalscore = 0
if num == 0:
finalscore = 0
elif num == 1:
finalscore = 50
elif num == 2:
finalscore = 60
else:
finalscore = 60+(num-2)*4
f.write(“%s\t%s\t%d\t%d\n” % (id,name,num,
finalscore))
#print(id,name,num ,finalscore)
break
if not found:
f.write(“%s\t%s\t%d\t%d\n” % (id,name,0,0))
f.close()
2.编写一个能在指定文件夹的指定后缀名的文本文件中寻找指定字符串的程序findtext.py,用法如下:
python findtext.py 文件夹 要找的字符串 后缀名1 后缀名2 后缀名3……
用法示例:
python findtext.py “c:\tmp\files” “XXXXX” txt html csv
程序在c:\tmp\files文件夹下的所有后缀名为”.txt”或”.html”或”.csv”的文件中寻找字符串”XXXXX”,还要递归查找所有子文件夹、子子文件夹下的文件,如果找到哪个文件包含” XXXXX”,则输出该文件带路径的文件名。注意,由于这些文件编码可能为utf-8,也可能为gbk,要求都能处理。对实在处理不了的文件,就跳过它,不能让程序RE中止。
解答:
import os
import sys
def walkPath(path,strToFind,exts):
lst = os.listdir(path)
for x in lst:
actualFileName = path + “/” + x # x不包括路径
if os.path.isfile(actualFileName):
ok = False
for ext in exts:
if x.lower().endswith(ext):
ok = True
break
if ok:
f = open(actualFileName,”r”,encoding=”utf-8″)
while True:
line = None
try:
line = f.readline()
except:
pass
if line == “”:
break
if strToFind in line:
print(“found in : “,actualFileName)
break
f.close()
else:
if walkPath(actualFileName,strToFind,exts ):
return True
return False
exts = []
for x in sys.argv[3:]:
exts.append(“.” + x)
walkPath(sys.argv[1],sys.argv[2],exts)
第十章习题解答
1.找出所有整数(P084):给一段文字,可能有中文,把里面的所有非负整数都找出来,不需要去掉前导0。如果碰到 “012.34”这样的就应该找出两个整数 012和34,碰到 0.050,就找出 0和050。
解答:
import re
#your code starts here
m = r”\d+”
#your code ends here
while True:
try:
s = input()
lst = re.findall(m,s)
for x in lst:
print(x)
except:
break
2.找出所有整数和小数(P085):给一段文字,可能有中文,把里面的所有非负整数和小数找出来,不需要去掉前导0或小数点后面多余的0, 然后依次输出。
解答:
import re
import sys
#your code starts here
m = r”\d+\.\d+|\d+”
#your code ends here
while True:
try:
s = input()
lst = re.findall(m,s)
for x in lst:
print(x)
except:
break
3.找出小于100的整数(P086):有给定的两行输入,在每一行的输入中提取在[0,100)内的整数(不包括100)并依次输出。注意要排除负数。
解答:
import re
m = r”(^|[^0-9-])(\d{1,2})([^0-9]|$)”
for i in range(2):
s = input()
lst = re.findall(m,s)
for x in lst:
#your code ends here
print(x[1])
#your code starts here
4.密码判断(P087):用户密码的格式是: 1) 以大写或小写字母开头 2) 至少要有8个字符,最长不限 3) 由字母、数字、下划线或 ‘-‘ 组成 输入若干字符串,判断是不是符合密码的条件。如果是,输出 yes 如果不是,输出 no。
解答:
import re
#your code starts here
m = r”[a-zA-Z][a-zA-z\d_-]{7}[a-zA-z\d_-]*$”
#your code ends here
while True:
try:
s = input()
if re.match(m,s) != None:
print(“yes”)
else:
print(“no”)
except:
break
5.找<>中的数(P088):输入一串字符,将输入中的,在<>里面的,没有前导0的少于4位的整数依次输出。单独的0也要输出。
解答:
import re
pt = ‘<(0|[1-9][0-9]{0,2})>’
#在<>里面的,没有前导0的少于4位的整数依次输出。单独的0也要输出。
n = int(input())
for i in range(n):
str = input()
y = re.findall(pt,str)
if y == []:
print(“NONE”)
else:
for x in y:
print(x,end = ” “)
print(“”)
6.检查美元(P089):给出一句话,判断这句话中是否存在规范书写的美元数纪录。美元数的规范如下:1)1.以$开始,$结束。2)数字为整数,从个位起,满3个数字用’,’分隔 正确的格式如:$1,023,032$ 或者 $2$,错误的格式如:$3,432,12$ 或者 $2。
解答:
import re
m = ‘\$\d{1,3}(,\d{3})*\$’
if len(re.findall(m,input())) > 0:
print(‘yes’)
else:
print(‘no’)
7.电话号码(P090):”<X>和它右边离他最近的”</X>”构成一个tag。电话号码由区号和号码构成,行如(20)-784。请找出tag中的电话号码。
解答:
import re
pt1 = “(<([a-z]+)>)(.*?)(</\\2>)”
pt2 = “(\((\d{1,2})\))-(\d+)”
n = int(input())
for ii in range(n):
s = input()
found = False
for x in re.finditer(pt1,s):
head = x.group(1)
tail = x.group(4)
str = x.group(3)
result = []
for y in re.finditer(pt2,str):
if len(y.group(3)) == 3:
result.append(y.group(2))
if len(result) > 0:
found = True
print(head,end=””)
for i in range(len(result)):
if( i == 0):
print(result[i],end=””)
else:
print(“,” + result[i],end=””)
print(tail)
if found == False:
print(“NONE”)
8.通讯记录(P091):”<X>”和它右边离他最近的”</X>”构成一个tag。通讯记录包含在tag中。每条通讯记录的格式为“%内容%邮箱”。“内容”部分是任意非空且不包含字符’%’的字符串。“邮箱”部分的格式是:“帐号@pku.edu.cn”或“帐号@stu.pku.edu.cn”。帐号是个满足以下两个条件的字符串:1)只包括大小写字母、数字和下划线,不能包含其他特殊字符;2)长度不为0,且不超过8个字符。请找出所有通讯记录。
解答:
import re
while True:
try:
s = input()
except:
break
print(“—-“)
pt = “<([a-zA-Z]+)>(.*?)</\\1>”
#r = re.findall(pt,”<xyz>bbs</xyz></xyz>abc<xy>kkk</bq>sfaf<bq>kkt</bq>bn”)
r = re.findall(pt,s)
if r == []:
print(“NONE”)
else:
pt = “%([^%]+)%([a-zA-Z0-9_]{1,8}
@(pku\.edu\.cn|stu\.pku\.edu\.cn))”
found = False
for e in r:
s = e[1]
for r in re.finditer(pt,s):
print(r.group(1),r.group(2))
found = True
if not found:
print(“NONE”)
第十一章习题解答
1.时间处理(P092):求从给定时刻开始过了给定时间后的时刻。
解答:
import datetime
while True:
try:
dt = input()
if dt.count(” “) > 2:
year, month, day, hour, mini = map(int,dt.split())
nowtime = datetime.datetime(year, month,
day, hour, mini)
else:
nowtime = datetime.datetime.strptime(dt,
“%m-%d-%Y %I:%M %p”)
# 由字符串生成
lst = input().split()
if len(lst) == 1:
delta = datetime.timedelta(seconds=int(lst[0]))
else:
day, hour, mini = map(int, lst)
delta = datetime.timedelta(days = day,
hours= hour,minutes=mini)
newtime = nowtime + delta
print(newtime.strftime(“%Y-%m-%d %H:%M:%S”))
except Exception as e:
#print(e)
break
2.密码生成器:随机生成一万个密码。密码由大小写字母、数字和下划线这四类字符构成。要求密码介于8到10位之间,且必须包含这四类字符。要求密码具有一定的概率均等性,即统计10000个密码,所有字母出现的概率基本相同,所有数字出现的概率基本相同。每个密码里有且只能有1个下划线,位置也要随机,最多有4个数字。
解答:
# 2.密码生成器:随机生成一万个密码。密码由大小写字母、数字和下划线这四类字符构成。要求密码介于8到10位之间,且必须包含这四类字符。要求密码具有一定的概率均等性,即统计10000个密码,所有字母出现的概率基本相同,所有数字出现的概率基本相同。每个密码里有且只能有1个下划线,位置也要随机,最多有4个数字。
# 解答:
import random
letters = “abcdefghijklmnopqrstuvwxyz”
numbers = “0123456789”
def genCode():
L = random.randint(8,10)
digitNum = random.randint(1,4)
letterNum = L – 1 – digitNum
result = [“_”]
for i in range(digitNum):
result.append(numbers[random.randint(0,9)])
for i in range(letterNum):
c = letters[random.randint(0, 25)]
if random.randint(0,1):
c = chr(ord(c) – ord(‘a’) + ord(“A”))
result.append(c)
random.shuffle(result)
return “”.join(result)
for i in range(10000):
print(genCode())
下面几道习题在配书资源中有详细信息和提示,如果要完成,请务必阅读。
3.用openpyxl处理excel文档:配书资源包中“第十一章习题3.zip”有一个多城市多月份多种商品销售情况的excel文档。指定特定城市和特定月份,请抽取该城市该月份的数据新建一个excel文档,对新文档的单元格样式有一定要求。
解答:
import openpyxl as pxl
from openpyxl.styles import Font,colors,
PatternFill,Alignment,Side,Border
import sys
if len(sys.argv) <= 1:
city = input(“请输入要查询的城市:”)
month = input(“请输入要查询的月份:”)
else:
city,month = sys.argv[1],int(sys.argv[2])
month = int(month)
book = pxl.load_workbook(r”C:\diskd\aMyClasses\文科计算机\讲义\excel讲义\数据透视表.xlsx”)
sheet = book[“原数据”]
result = {}
cityFound = False
monthFound = False
for row in sheet[2:sheet.max_row]:
dt,ct,product,num,sales,cost = row
numFormat = sales.number_format
#dt = datetime.datetime.strptime(dt.value,r”%Y/%m/%d”)
if ct.value.strip() == city:
cityFound = True
if month == dt.value.month:
monthFound = True
if product.value.strip() in result:
result[product.value.strip()][0] += \
num.value
result[product.value.strip()][1] += \
sales.value
result[product.value.strip()][2] += \
cost.value
else:
result[product.value.strip()] = \
[num.value,sales.value ,cost.value]
if not cityFound:
print(“没有这个城市的销售记录”)
exit()
if not monthFound:
print(“该城市没有指定月份的销售记录”)
exit()
filename = city + str(month) + “月销售情况.xlsx”
lst = list(result.items())
lst.sort(key = lambda x:-x[1][0])
book = pxl.Workbook()
sheet = book.active
sheet.title = filename
sheet.append((“产品类别”,”数量”,”销售额”,”成本”,”利润”))
i = 2
for x in lst:
r = [x[0],x[1][0],x[1][1],x[1][2]]
r.append(“=C%d-D%d” % (i,i))
sheet.append(r)
i += 1
for row in sheet.rows:
for i in range(2,5):
row[i].number_format = numFormat
for x in “CDE”:
sheet.column_dimensions[x].width = 14
for x in ‘ABCDE’:
sheet[x +”1″].fill = PatternFill(patternType=’solid’,
fgColor=”00ff00″)
book.save(“c:/tmp/” + filename)
★ 4.反转照片并添加拍摄时间:配书资源包中“第十一章习题4.zip”有一些照片,有的照片上下颠倒了。请在这些照片上面打上拍摄时间形成新照片。如果照片是上下颠倒的,那么要先颠倒过来。
解答:
import sys
import os
import time
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
#设置所使用的字体
myFont= ImageFont.truetype(“C:\Windows\Fonts\msmhei.ttf”, 24)
def isDark(color): #color is rgba color
brightness = (color[0]/255 * 299 + color[1]/255 * 587 + \
color[2]/255 * 114) / 1000
if brightness > 0.5:
return False
else:
return True
def isUpsideDown(data,w,h):
if h < 30:
return False
updark = 0
for i in range(10):
for j in range(w):
color = data[j,i]
if isDark(color):
updark+= 1
else:
updark -= 1
downdark = 0
for i in range(10):
for j in range(w):
color = data[j,h-1-i]
if isDark(color):
downdark+= 1
else:
downdark -= 1
if updark > 0 and downdark < 0:
return True
return False
def TimeStampToTime(timestamp):
timeStruct = time.localtime(timestamp)
#return time.strftime(‘%Y-%m-%d %H:%M:%S’,timeStruct)
str = time.strftime(‘%Y-%m-%d’,timeStruct)
pos = str.find(“-“)
str = str[:pos] + “年” + str[pos+1:]
pos = str.find(“-“)
str = str[:pos] + “月” + str[pos+1:] + “日”
return str
os.makedirs(“result”)
lst = os.listdir() #列出当前文件夹下所有文件和文件夹
for x in lst:
filePath = x
if os.path.isfile(filePath): #如果x是文件
if x.lower().endswith(“.jpg”) or \
x.lower().endswith(“.png”):
t = os.path.getctime(filePath)
timeStr = TimeStampToTime(t)
img = Image.open(x)
w,h = img.size
fw,fh = myFont.getsize(timeStr)
#draw.text((0,0),timeStr)
imgRgba = img.convert(‘RGBA’)
datalist = imgRgba.load()
print(“w=%d,h=%d” % (w,h))
if isUpsideDown(datalist,w,h):
img = img.transpose(Image.FLIP_TOP_BOTTOM)
imgRgba = img.convert(‘RGBA’)
datalist = imgRgba.load()
draw = ImageDraw.Draw (img)
dark = 0
for i in range(fw):
for j in range(fh):
color = datalist[w-fw+i,j + h-fh]
if isDark(color):
dark += 1
else:
dark -= 1
if dark > 0:
draw.text((w-fw, h-fh),timeStr , (255, 255, 255),
font=myFont)
else:
draw.text((w-fw, h-fh),timeStr , (0,0,0),
font=myFont)
img.save(“result\\” + x[:-4] + “.png”,”png” )
#一律转成 png格式存
★★ 5.给照片加拍摄地址:手机拍摄的照片可能会有拍摄地点的gps经纬度坐标信息。资源包中“第十一章习题5.zip”给几张这样的照片,请编程提取经纬度,然后根据经纬度搜寻对应的地址(国家、城市、街道、门牌号等),将地址打印在照片上形成新照片。
解答:
from PIL import Image,ImageDraw,ImageFont,ExifTags
from geopy.geocoders import Nominatim
def getExifData(img):
try:
if hasattr( img, ‘_getexif’ ): #hasattr是python函数
return img._getexif()
except :
return None
return None
def getExifKeyCode(keyStr):
for x in ExifTags.TAGS.items():
if x[1] == keyStr:
return x[0]
return None
def writeTextToImage(img,text,myFont):
#往照片文件 oldFileName中以字体myFont写入text并存为newFileName
w, h = img.size
fw, fh = myFont.getsize(text) #text的高度,宽度
draw = ImageDraw.Draw(img)
draw.text((w – fw, h – fh), text, (255, 255, 255),
font=myFont,)
#draw.rectangle((100,100,200,200),fill=135)
def getAddress(geolocator,coord):
try:
print(“coord”,coord )
location = geolocator.reverse(coord)
print(location.address)
adr = location.raw[“address”]
print(adr)
return location.address
if “region” in adr:
return adr[“region”]
elif “state” in adr:
return adr[“state”]
else:
return “”
except Exception as e:
print(e)
return “”
def countDegree(d):
if type(d[0]) != tuple:
print(“gps is float”)
return float(d[0] + d[1]/60 + d[2] / 3600)
else:
print(“gps is tuple”)
return d[0][0]/d[0][1] + d[1][0]/d[1][1] / 60 + \
d[2][0]/d[2][1] / 3600
def makeCoordStr(gpsInfo):
NS,EW = gpsInfo[1],gpsInfo[3]
A = countDegree(gpsInfo[2])
L = countDegree(gpsInfo[4])
if NS == “S”:
A = – A
if EW == “W”:
L = – L
return str(A) + “,” + str(L)
def correctOrientation(img):
# 根据exif判断,img里的图像如有颠倒或旋转则生成一幅将其摆正的图返回
if hasattr(img, “_getexif”): # 判断img有没有_getexif函数
exif = img._getexif() #获取图像exif信息,返回值是个字典
if exif != None:
orientation = exif[getExifKeyCode(‘Orientation’)]
if orientation == 3: # 手机顶部朝右拍
img = img.rotate(180, expand=True)
elif orientation == 6: # 手机正常竖着拍(顶部朝上)
img = img.rotate(270, expand=True)
elif orientation == 8: # 手机顶部朝下拍
img = img.rotate(90, expand=True)
return img
def main():
# geolocator = Nominatim(user_agent=”kktfor_text”)
# print(getAddress(geolocator,(“32.49196,100.6464”)))
# print(“ok,ok”)
# exit()
myFont = ImageFont.truetype(“C:\\Windows\\Fonts\\simhei.ttf”,
60)
img = Image.open(“c:/tmp/pic/iphone.jpg”) #冰岛
#img = Image.open(“c:/tmp/pic/20170809_125846_IP.JPG”) #挪威
exif = getExifData(img)
img = correctOrientation(img)
if exif == None:
print(“No exif data”)
return
shootTime = exif[getExifKeyCode(“DateTimeOriginal”)]
# shootTime是字符串,格式: 2017:08:05 19:16:02
address = “”
gpsCode = getExifKeyCode(‘GPSInfo’)
if gpsCode in exif:
geolocator = Nominatim(user_agent=”kktfor_text”)
gpsInfo = exif[gpsCode]
print(gpsInfo)
if 1 in gpsInfo:
coordStr = makeCoordStr(gpsInfo)
address = getAddress(geolocator,coordStr)
info = address + “****” + shootTime
writeTextToImage(img, info,myFont)
img.show()
return
main()
第十二章习题解答
下面几道习题在配书资源中有详细信息和提示,如果要完成,请务必阅读。
1.用pandas处理excel文档:配书资源包中有一个多城市多月份多种商品销售情况的excel文档。指定特定城市和特定月份,请抽取该城市该月份的数据新建一个excel文档。本题资源包和第十一章第3题相同。
解答:
import pandas as pd
import datetime
import sys
pd.set_option(‘display.unicode.east_asian_width’,True)
if len(sys.argv) <= 1:
city = input(“请输入要查询的城市:”)
month = input(“请输入要查询的月份:”)
else:
city,month = sys.argv[1],int(sys.argv[2])
month = int(month)
dt = pd.read_excel(“数据透视表.xlsx”,sheet_name=[‘原数据’],
index_col=1)
df = dt[‘原数据’] #dt是字典,df是DataFrame
view = None
try:
view = df.loc[‘苏州’]
except:
pass
if view is None:
print(“没有这个城市的销售记录”)
exit()
monthFound = False
result = {}
for row in view.values:
dt,product,num,sales,cost = row
if month == dt.month:
monthFound = True
if product in result:
result[product][0] += num
result[product][1] += sales
result[product][2] += cost
else:
result[product] = [num,sales,cost,sales-cost]
if monthFound == False:
print(“无该月销售记录”)
exit()
items = []
titles = [‘数量’,’销售额’,’成本’,’利润’]
data = []
for x in result.items():
items.append(x[0])
data.append(x[1])
df = pd.DataFrame(data=data,index = items,columns = titles)
writer = pd.ExcelWriter(city+str(month) +”月销售表.xlsx”)
df.to_excel(writer,sheet_name=city+str(month) +”月销售情况”)
writer.save()
print(“成功生成:” + city+str(month) +”月销售表.xlsx”)
2.三国人名词云:“词云”是一种有趣的数据展示方式,本书并未提及。学习Python,自己上网搜索解决问题办法的自学能力非常重要。给定资源包中“第十二章习题2.zip”的三国演义文本和三个.png图片,请制作分布在这三个图片上的词云。
解答:
import matplotlib.pyplot as plt
from wordcloud import WordCloud
import PIL.Image as image
import jieba
import numpy as np
mask = np.array(image.open(“love.png”))
text_from_file_with_apath = open(r”三国演义utf8.txt”,
encoding=”utf-8″).read()
wordlist_after_jieba = jieba.lcut(text_from_file_with_apath)
for i in range(len(wordlist_after_jieba)):
if len(wordlist_after_jieba[i]) == 1:
continue
elif wordlist_after_jieba[i] == “诸葛亮” or
wordlist_after_jieba[i] == “孔明曰”:
wordlist_after_jieba[i] = “孔明”
elif wordlist_after_jieba[i] == “关公” or
wordlist_after_jieba[i] == “云长” or
wordlist_after_jieba[i] == “关云长”:
wordlist_after_jieba[i] = “关羽”
elif wordlist_after_jieba[i] == “玄德”
or wordlist_after_jieba[i] == “玄德曰”:
wordlist_after_jieba[i] = “刘备”
elif wordlist_after_jieba[i] == “孟德” or
wordlist_after_jieba[i] == “操贼”:
wordlist_after_jieba[i] = “曹操”
wl_space_split = ” “.join(wordlist_after_jieba)
excludes = {‘汉中’, ‘将军’,’丞相’,’不能’,’荆州’,’却说’,’二人’,’不可’ ,’商议’,’如何’,’主公’,’军士’,’左右’,’军马’,’引兵’,’次日’,’大喜’,’东吴’,’天下’,’于是’,’今日’,’不敢’,’魏兵’,’陛下’}
my_wordcloud = WordCloud(
font_path=”C:\Windows\Fonts\STXINGKA.TTF”,
background_color=”white”,
stopwords=excludes,
mask= mask,
max_words=10,height=400,width=800).generate(
wl_space_split)
plt.imshow(my_wordcloud)
plt.axis(“off”)
plt.show()
点点赞赏,手留余香
给TA打赏
评论0