蓝桥杯Python算法复习系列(三):Python常用功能详解
3.1.1 输入和输出
"""多行输入"""
a=int(input())
b=input().split()
# 读取所有整数,用split分开
c=[int(i)for i in input().split()]
d=list(map(int,input().split()))
# 不用a[0]
e=[0]+[int(i)for i in input().split()]
"""N个整数A"""
N=int(input())
A=[]
for i in range(N):
A.append(int(input()))
# 用map转化
n,k=map(int,input().split())
w=[]
h=[]
for i in range(n):
a,b=map(int,input().split())
w.append(a)
h.append(b)
"""二维数组的输入"""
# m行
f=input()
n,m,T=[int(i)for i in f.split()]
a=[] #a[i][]
for i in range(m):
a.append(int(i)for i in input().split())
"""间隔数字"""
# h1:m1:s1
# h2:m2:s2
# 切片
line=input().split()
h1=int(line[0][0:2])
m1=int(line[0][3:5])
s1=int(line[0][6:8])
#split
line=input().split()
h2,m2,s2=map(int,line[1].split(':'))
"""带格式输出"""
print('{:.4f}'.format(n))
print("%.4f" %n)
print(round(n,4))
print("{:0>2d}:{:0>2d}:{:0>2d}".format(hh,mm,ss))
print("%02d:%02d:%02d"%(hh,mm,ss))
3.1.2 字符串
- split()
- format()
- 字符串切片
- 查找 in,find(),index(),rindex()
- 个数 count()
- 替换 replace
- 合并 join()
- 大小写 capitalize(),title(),upper(),lower()
- strip()
- 检查 isalpha(),isdigit(),isalnum(),isspace()
- 比较,连接,复制
- 对齐.center() .ljust() .rjust()
P4050
1.烬寂海之谜 – 蓝桥云课
现在给你一个字符串 S(主串),还有若干个模式串 P。你需要统计每一个模式串在主串中出现的次数。
#输入 S=input() n=int(input()) while n>0: n-=1 P=input() print(S.count(P))
当S="aaaa",P="aa"时答案为3,上述代码输出为2,不能通过全部测试用例
#输入 S=input() n=int(input()) while n>0: n-=1 P=input() count=0 for i in range(len(S)): if P == S[i:i+len(P)]: count+=1 print(count)
从S[i]开始匹配P。
上述代码可以通过全部测试用例。
使用len(S) - len(P) + 1
是为了优化字符串匹配的遍历范围,避免不必要的遍历。当i + len(P)
超过len(S)
时,S[i:i+len(P)]
会返回一个长度小于len(P)
的子串,这种子串不可能与P
匹配。S = input() # 输入字符串 S n = int(input()) # 输入整数 n while n > 0: # 循环 n 次 n -= 1 # 每次循环减少 n 的值 P = input() # 输入字符串 P count = 0 # 初始化计数器 for i in range(len(S) - len(P) + 1): # 优化遍历范围 if P == S[i:i+len(P)]: # 检查子串是否匹配 count += 1 # 如果匹配,计数器加 1 print(count) # 输出统计结果
3.1.3 日期库
date类
date(year,month,day)
today()
strftime(format)
isoformat()
weekday()
isoweekday()
replace(year,month,day)
toordinal()
timedelta
time类
time(hour,minute,second,microsecond)
strf(format)
datetime类
%y |
%Y |
%m | %d |
%H | %I |
%M | %S |
%a | %A |
%b | %B |
P1452
1.时间显示 – 蓝桥云课
小蓝要和朋友合作开发一个时间显示的网站。
在服务器上,朋友已经获取了当前的时间,用一个整数表示,值为从 1970 年 1 月 11日 00:00:00 到当前时刻经过的毫秒数。
现在,小蓝要在客户端显示出这个时间。小蓝不用显示出年月日,只需要显示出时分秒即可,毫秒也不用显示,直接舍去即可。
给定一个用整数表示的时间,请将这个时间对应的时分秒输出。
# 输入 from datetime import * n=int(input()) s=datetime(1970,1,1) d=timedelta(milliseconds=1) result=s+n*d print(result.strftime("%H:%M:%S"))
P729
1.星期几 – 蓝桥云课
from datetime import * count=0 for i in range(1949,2013): a=datetime(i,10,1) if a.weekday()==6: count+=1 print(count)
datetime
类可以处理日期和时间,而date
类只能处理日期。由于我们不需要时间信息,使用date
更为简洁。from datetime import date count = 0 for i in range(1949, 2013): a = date(i, 10, 1) if a.weekday() == 6: count += 1 print(count)
以下为练习题,来源于蓝桥杯题库搜索题号
P711
大数学家高斯有个好习惯:无论如何都要记日记。
他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210。
后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?
高斯出生于:1777 年 4 月 30 日。
在高斯发现的一个重要定理的日记上标注着:5343,因此可算出那天是:1791 年 12 月 15 日。
高斯获得博士学位的那天日记上标着:8113。
请你算出高斯获得博士学位的年月日。
提交答案的格式是:yyyy−mm−dd, 例如:1980−03−21。
from datetime import *
d=timedelta(days=1)
begin=datetime(2004,5,20)
end=datetime(2025,3,12)
days=end-begin
print(days.days,days.days/365)
# 7601 20.824657534246576
尝试计算一下自己活了多少天,没想到已经活了这么久🫤!
不使用datetime会比较浪费时间
# 高斯出生日期
birth_year = 1777
birth_month = 4
birth_day = 30
# 日记标注的天数
diary_days = 8113
# 当前日期
current_year = birth_year
current_month = birth_month
current_day = birth_day
# 逐日累加
for _ in range(diary_days - 1): # 减去1,因为出生日算第1天
# 判断当前月份的天数
if current_month in [1, 3, 5, 7, 8, 10, 12]:
days_in_month = 31
elif current_month == 2:
# 判断闰年
if (current_year % 4 == 0 and current_year % 100 != 0) or (current_year % 400 == 0):
days_in_month = 29
else:
days_in_month = 28
else:
days_in_month = 30
# 增加一天
current_day += 1
# 如果超过当前月份的天数,进入下一个月
if current_day > days_in_month:
current_day = 1
current_month += 1
# 如果超过12个月,进入下一年
if current_month > 12:
current_month = 1
current_year += 1
# 输出结果
print(f"{current_year}-{current_month:02d}-{current_day:02d}")
from datetime import *
d=timedelta(days=1)
begin=date(1777,4,30)
end=begin+d*8112
print(end)
考试的时候怎么知道写8112而不是8113呢?太容易错了,出生是第一天1开始计数(第一天为1),出生第二天开始加1,可以通过给的例子进行验证。
import os
import sys
# 请在此输入您的代码
from datetime import *
d=timedelta(days=1)
begin=datetime(1777,4,30)
end=begin+d*8112
print(end.strftime("%Y-%m-%d"))
P670
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
在 X 星系的广袤空间中漂浮着许多X星人造“炸弹”,用来作为宇宙中的路标。 每个炸弹都可以设定多少天之后爆炸。
比如:阿尔法炸弹 2015 年 1 月 1日放置,定时为1日放置,定时为15天,则它在天,则它在2015年年1月16 日爆炸。
有一个贝塔炸弹,2014年 11 月 9 日放置,定时为 1000 天,请你计算它爆炸的准确日期。
请输出该日期,格式为 yyyy−mm−dd 即 4 位年份 2 位月份 2 位日期。比如:2015−02−19。
本题中1000天根据提供的例子可以验证是从0(第一天为0)开始计数。
from datetime import *
begin=date(2014,11,9)
d=timedelta(days=1)
end=begin+d*1000
print(end)
P103
小明正在整理一批历史文献。这些历史文献中出现了很多日期。小明知道这些日期都在 1960 年 1 月 1 日至 2059 年 12 月 31 日。令小明头疼的是,这些日期采用的格式非常不统一,有采用年/月/日的,有采用月/日/年的,还有采用日/月/年的。
更加麻烦的是,年份也都省略了前两位,使得文献上的一个日期,存在很多可能的日期与其对应。
比如 02/03/04,可能是 2002 年 03 月 04 日、2004 年 02 月 03 日或 2004 年 03 月 02 日。
给出一个文献上的日期,你能帮助小明判断有哪些可能的日期对其对应吗?
输出若干个不相同的日期,每个日期一行,格式是 "yyyy−MM−dd"。多个日期按从早到晚排列。
#输入 n=input() #01/34/67 n1=int(n[0:2]) n2=int(n[3:5]) n3=int(n[6:8]) # 年1960-2059:60-0-59 # 0~59+2000 60~69+1900 #最多三种情况,使用函数处理重复操作 #n1,n2,n3 #n3,n1,n2 #n3,n2,n1 def f(n1,n2,n3): try: if n1<=59: print(date(n1+2000,n2,n3)) else: print(date(n1+1900,n2,n3)) except: pass
from datetime import *
def f(n1,n2,n3):
try:
if 0<=n1<=59:
return date(n1+2000,n2,n3)
elif 60<=n1<=99:
return date(n1+1900,n2,n3)
else:
pass
except:
pass
if __name__ =="__main__":
# 输入
n = input() # 01/34/67
n1 = int(n[0:2])
n2 = int(n[3:5])
n3 = int(n[6:8])
# 如果输入为22/01/01,则输出答案会重复
res=set()
result=[(n1,n2,n3),(n3,n1,n2),(n3,n2,n1)]
for n1,n2,n3 in result:
d=f(n1,n2,n3)
if d:
res.add(str(d))
if res: #没有也能通过,测试用例没有输出空行的情况
print('\n'.join(sorted(list(res))))
res
列表中可能包含 None
,而 None
不是 date
对象。
from datetime import date
def f(n1, n2, n3):
"""检查日期是否有效,并返回日期对象"""
try:
if 0 <= n1 <= 59:
return date(n1 + 2000, n2, n3)
elif 60 <= n1 <= 99:
return date(n1 + 1900, n2, n3)
else:
return None
except ValueError:
return None
if __name__ == "__main__":
# 输入
n = input() # 例如:01/34/67
n1 = int(n[0:2])
n2 = int(n[3:5])
n3 = int(n[6:8])
# 尝试不同的组合
res = set()
result = [(n1, n2, n3), (n3, n1, n2), (n3, n2, n1)]
for n1, n2, n3 in result:
d = f(n1, n2, n3)
if d: # 过滤掉 None
res.add(d)
# 输出结果
for d in sorted(res):
print(d)
使代码更加简洁,对结果没有影响
from datetime import date
def f(n1, n2, n3):
try:
return date(n1+2000 if 0<=n1<=59 else n1+1900,n2,n3)
except ValueError:
return None
if __name__ == "__main__":
n1,n2,n3=map(int,input().split("/"))
res = set()
for n1, n2, n3 in [(n1, n2, n3), (n3, n1, n2), (n3, n2, n1)]:
d = f(n1, n2, n3)
if d:
res.add(d)
for d in sorted(res):
print(d)
P614
2000 年的 1 月 1 日,是那一年的第 11 天。
那么,2000年的 5 月 4 日,是那一年的第几天?
from datetime import *
a=date(2000,5,4)
b=date(2000,1,1)
c=(a-b).days #时间差
print(c+1)
P498
给定一个 8 位数的日期,请你计算该日期之后下一个回文日期和下一个 ABABBABA 型的回文日期各是哪一天。
from datetime import *
def is_valid_date(date_str):
"""检查日期字符串是否为有效日期"""
try:
datetime.strptime(date_str, "%Y%m%d")
return True
except ValueError:
return False
d=input()
da=int(d)
flag=True
for i in range(1,99999999-da):
da+=1
d=str(da)
if d==d[::-1]:
if is_valid_date(d):
if flag:
print(d)
flag=False
if d[0]==d[2]==d[5]==d[7] and d[1]==d[3]==d[4]==d[6]:
if is_valid_date(d):
print(d)
break
上述代码会有一个用例超时。可以使用 datetime
对象和 timedelta
递增日期,使用 datetime.strftime
将日期转换为字符串。
from datetime import datetime, timedelta
d = input()
da = int(d)
current_date = datetime.strptime(d, "%Y%m%d")
flag = True
while True:
# 递增日期
current_date += timedelta(days=1)
d = current_date.strftime("%Y%m%d")
if d == d[::-1]:
if flag:
print(d) # 输出第一个回文日期
flag = False
if d[0] == d[2] == d[5] == d[7] and d[1] == d[3] == d[4] == d[6]:
print(d)
break
P579
小蓝每天都锻炼身体。
正常情况下,小蓝每天跑 1 千米。如果某天是周一或者月初(1 日),为了激励自己,小蓝要跑 2 千米。如果同时是周一或月初,小蓝也是跑 2 千米。
小蓝跑步已经坚持了很长时间,从 2000 年 1 月 1 日周六(含)到 2020 年 10 月 1 日周四(含)。请问这段时间小蓝总共跑步多少千米?
看清起始和结束日期,不要写错或计算错,包括第一天,时间差加一。
可以使用 datetime
对象和 timedelta
递增日期。
from datetime import *
begin=date(2000,1,1)
end=date(2020,10,1)
days=(end-begin).days + 1
counts=0
for i in range(days):
if begin.weekday()==0 or begin.day==1:
counts+=2
else:
counts+=1
begin+=timedelta(days=1)
print(counts)
或者使用while循环
from datetime import *
begin=date(2000,1,1)
end=date(2020,10,1)
counts=0
while begin<=end:
if begin.weekday()==0 or begin.day==1:
counts+=2
else:
counts+=1
begin+=timedelta(days=1)
print(counts)
P175 航班时间
对于一个可能跨时区的航班,给定来回程的起降时间。假设飞机来回飞行时间相同,求飞机的飞行时间。
#去 t1 t1+tf t1+tf+tc=t2
#回 t3 t3+tf t3+tf-tc=t4
#相加 t1+t3+2tf=t2+t4 2tf=t2+t4-t1-t3
from datetime import *
def f(t):
if len(t.split())==1:
t = t.split(":")
t = int(t[0]) * 3600 + int(t[1]) * 60 + int(t[2])
return t
else:
t1, t2 = t.split()
t2 = int(t2[2]) * 3600 * 24
t1 = f(t1)
return t1 + t2
# 输入
T = int(input())
for i in range(T):
t1, t2 = input().split(maxsplit=1)
t3, t4 = input().split(maxsplit=1)
tf=(f(t2)+f(t4)-f(t1)-f(t3))//2
H=tf//3600
tf=tf%3600
M=tf//60
S=tf%60
print("%02d:%02d:%02d"%(H,M,S))
P2119
请问, 总共有多少个时间是这种年份写成 4 位、月日写成 4 位、时间写成 4 位后由 3 个一种数字和 1 个另一种数字组成。
#0000 0000 0000 枚举
#月日0111,1011,1101,1110
#月日0222
#月日1112,1121,1211,1113,1114,1115,1116,1117,1118,1119
#月日1222
#对应的合法时间数
#4444,4,4443332222,4
#年份没有限制
print((4*9+3*3+2*4)*4)
P3492
小蓝现在有一个长度为 100 的数组,数组中的每个元素的值都在 0 到 9 的范围之内。数组中的元素从左至右如下所示:
5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2 7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1 0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
现在他想要从这个数组中寻找一些满足以下条件的子序列:
- 子序列的长度为 8;
- 这个子序列可以按照下标顺序组成一个 yyyymmdd 格式的日期,并且要求这个日期是 2023 年中的某一天的日期,
请你帮小蓝计算下按上述条件一共能找到多少个不同的 2023 年的日期。对于相同的日期你只需要统计一次即可。
from datetime import datetime, timedelta
input_string = '''5 6 8 6 9 1 6 1 2 4 9 1 9 8 2 3 6 4 7 7 5 9 5 0 3 8 7 5 8 1 5 8 6 1 8 3 0 3 7 9 2
7 0 5 8 8 5 7 0 9 9 1 9 4 4 6 8 6 3 3 8 5 1 6 3 4 6 7 0 7 8 2 7 6 8 9 5 6 5 6 1 4 0 1
0 0 9 4 8 0 9 1 2 8 5 0 2 5 3 3
'''
# 将字符串按空格分割成列表
input_list = input_string.split()
start_date = datetime(2023, 1, 1)
end_date = datetime(2023, 12, 31)
result = 0
# 循环遍历从起始日期到结束日期的每一天
while end_date >= start_date:
formatted_date = start_date.strftime('%Y%m%d')
# 初始化匹配数字的计数器
matched_count = 0
# 遍历输入列表中的每个数字
for num in input_list:
if matched_count == 8:
# 如果找到 8 位数字与当前日期相等,结果加 1
result += 1
break
if formatted_date[matched_count] == num:
# 如果当前数字与日期中的对应数字相等,匹配计数器加 1
matched_count += 1
start_date += timedelta(days=1)
print(result)
3.1.4 set和字典去重
1.set():存储的元素是唯一的
2.字典:字典的键是唯一的
作者:寒舍书生