蓝桥杯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 字符串

  1. split()
  2. format()
  3. 字符串切片
  4. 查找 in,find(),index(),rindex()
  5. 个数 count()
  6. 替换 replace
  7. 合并 join()
  8. 大小写 capitalize(),title(),upper(),lower()
  9. strip()
  10. 检查 isalpha(),isdigit(),isalnum(),isspace()
  11. 比较,连接,复制
  12. 对齐.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
    

    现在他想要从这个数组中寻找一些满足以下条件的子序列:

    1. 子序列的长度为 8;
    2. 这个子序列可以按照下标顺序组成一个 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.字典:字典的键是唯一的

    作者:寒舍书生

    物联沃分享整理
    物联沃-IOTWORD物联网 » 蓝桥杯Python算法复习系列(三):Python常用功能详解

    发表回复