鱼C论坛

 找回密码
 立即注册
查看: 4871|回复: 38

[技术交流] Python:每日一题 130

[复制链接]
发表于 2017-12-7 20:53:59 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 jerryxjr1220 于 2017-12-11 10:45 编辑

首先我们的玩法做了一下改变:

1. 楼主不再提供答案。
2. 请大家先独立思考”,再参考其他鱼油的解答,这样才有助于自己编程水平的提高。
3. 鼓励大家积极答题,奖励的期限为出题后24小时内。
4. 根据答案的质量给予1~3鱼币的奖励。


题目:特别的生日
我们知道任何一个日期都可以用8个数字写成“yyyymmdd”这种形式,例如“20010101”表示2001年1月1日,小明发觉自己的生日非常特别,因为当自己的生日写成“yyyymmdd”的形式后,发觉这8个数字各不相同,而且从自己的生日以后,一直到今天就再也没有出现这样的日期了。请问小明的生日是哪年的哪天?请用程序解答。

给点提示好了,看到不少鱼油都是自己手动写日期循环,非常麻烦,其实可以利用datetime的python内置库,算日期这种小事就交给它吧^_^

本帖被以下淘专辑推荐:

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-12-7 21:08:56 | 显示全部楼层
贫穷限制了我的想象!!!
不知小明同学可以活多久?
不知“再也没有出现过这样的日期”中的“这样”是哪种程度的“这样”?

点评

这个和小明可以活多久没有关系。再没有出现过把日期写成8个数字,这8个数字相互不重复的日期。  发表于 2017-12-8 10:33
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-12-7 21:59:41 | 显示全部楼层
本帖最后由 wyp02033 于 2017-12-7 22:02 编辑
  1. from time import perf_counter

  2. def is_leap_year(year):
  3.     if (year % 4 == 0 and year % 100 != 0) or year % 400 == 0:
  4.         return True
  5.     else:
  6.         return False

  7. def find_the_birthday():
  8.     year = 2017
  9.     months = [i for i in range(1, 13)]
  10.     days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
  11.     i = 11
  12.     while True:
  13.         for day in range(days[i], 0, -1):
  14.             birthday = str(year) + "%02d" % months[i] + "%02d" % day           
  15.             if len(set(birthday)) == len(birthday):
  16.                 return birthday
  17.         i -= 1

  18.         if i < 0:
  19.             year -= 1
  20.             i = 11
  21.             if is_leap_year(year):
  22.                 days[1] = 29

  23. if __name__ == '__main__':
  24.     start = perf_counter()
  25.     print(find_the_birthday())
  26.     end = perf_counter()
  27.     print("time uesd:", end - start)
复制代码

19870625
time uesd: 0.012000967581096625

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-7 22:01:44 | 显示全部楼层
结果是:19870625    即1987年6月25日
  1. stor=[]
  2. for d1 in range(10):
  3.     for d2 in range(10):
  4.         if d1!=d2:
  5.             for d3 in range(10):
  6.                 if (d1!=d3)&(d2!=d3):
  7.                     for d4 in range(10):
  8.                         if(d1!=d4)&(d2!=d4)&(d3!=d4):
  9.                             for d5 in range(10):
  10.                                 if(d1!=d5)&(d2!=d5)&(d3!=d5)&(d4!=d5):
  11.                                     for d6 in range(10):
  12.                                         if(d1!=d6)&(d2!=d6)&(d3!=d6)&(d4!=d6)&(d5!=d6):
  13.                                             for d7 in range(10):
  14.                                                 if(d1!=d7)&(d2!=d7)&(d3!=d7)&(d4!=d7)&(d5!=d7)&(d6!=d7):
  15.                                                     for d8 in range(10):
  16.                                                         if(d1!=d8)&(d2!=d8)&(d3!=d8)&(d4!=d8)&(d5!=d8)&(d6!=d8)&(d7!=d8):
  17.                                                             data=d1+d2*10+d3*100+d4*1000+d5*10000+d6*100000+d7*1000000+d8*10000000
  18.                                                             day=d1+d2*10
  19.                                                             month=d3+d4*10
  20.                                                             if (month in {1,3,5,7,8,10,12})&(data <=20171207)&(day<=31):
  21.                                                                 stor.append(data)
  22.                                                             if (month in {4,6,11})&(data <=20171207)&(day<=30):
  23.                                                                 stor.append(data)
  24.                                                    
  25.                                                             if (data <=20171207)&(day<=29)&(month==2):
  26.                                                                 stor.append(data)
  27.                                                             

  28. print max(stor)
复制代码

评分

参与人数 1荣誉 +1 鱼币 +1 贡献 +1 收起 理由
jerryxjr1220 + 1 + 1 + 1 答题奖励,程序的写法可以优化

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-7 22:49:23 | 显示全部楼层
本帖最后由 小宏~ 于 2017-12-7 22:51 编辑
  1. print("+++++++++小宏最帅+++++++\n")
  2. a={1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0}
  3. m=2017
  4. count=0
  5. #假设小明在100岁之内
  6. for i in range(100):
  7.   n=int(m-i)
  8.   a[1]=(n//1000)
  9.   a[2]=(n%1000//100)
  10.   a[3]=(n%100//10)
  11.   a[4]=(n%10)
  12.   for j in range(1,13):
  13.     a[5]=(j//10)
  14.     a[6]=(j%10)
  15.     for x in range(1,32):
  16.       a[7]=(x//10)
  17.       a[8]=(x%10)
  18.       for i in range(1,9):
  19.         for j in range(i+1,9):
  20.           if(a[i]!=a[j]):
  21.             count=count+1
  22.       if(count==28):
  23.         print("他的生日是:%d %d %d %d年 %d %d月 %d %d日" %(a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8]))
  24.         exit()
  25.       count=0
  26.       
复制代码

点评

答案不正确  发表于 2017-12-8 10:36
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-7 23:19:12 | 显示全部楼层
  得到好多个答案,因为“从自己的生日以后,一直到今天就再也没有出现这样的日期了。” 好些符合这句话的答案,让老师见笑了。期待看到精选答案~

我的程序如下:

def DifferentNumber(string):
    #判断字符串中字符各不相同
    temp =0  #用于所有字符是否各不相同
    for char in string:
        if string.count(char) == 1:
            temp += 1
        else:
            continue
    if temp == 8:
        return True
    else:
        return False


for year in range(1950,2018):       #年份
    for month in range(1,13):       #月份
        if month < 10:
            month = '0' + str(month)
        else:
            month = str(month)
        for day in range(1,32):     #日期
            if day < 10:
                day = '0' + str(day)
            else:
                day = str(day)
            #8位数字各不相同,即每位数字只出现过一次
            birthday = str(year) + month + day
            if DifferentNumber(birthday):
                print(birthday)

点评

答案是唯一的,你的答案是哪个?  发表于 2017-12-8 10:38
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 1 反对 0

使用道具 举报

发表于 2017-12-7 23:34:44 | 显示全部楼层
本帖最后由 shigure_takimi 于 2017-12-8 08:44 编辑
  1. def isRunnian(year):
  2.     return year%400==0 or (year%4==0 and year%100!=0)

  3. def getThatDay():
  4.     for year in range(2017,1000,-1):   #1988,1989,1990-1999,2000-2017都很显然不符合要求,本来可以不用循环的。
  5.         daysOfYear = [31,29,31,30,31,30,31,31,30,31,30,31] if isRunnian(year) else\
  6.                      [31,28,31,30,31,30,31,31,30,31,30,31]
  7.         for month  in range(12,0,-1):
  8.             for day in range(daysOfYear[month-1],0,-1):
  9.                 if len(set(str(year).zfill(4)+str(month).zfill(2)+str(day).zfill(2))) == 8:
  10.                     return str(year).zfill(4)+'-'+str(month).zfill(2)+'-'+str(day).zfill(2)

  11. print(getThatDay())


  12. ##    >>>
  13. ##    1987-06-25
复制代码


  1. 改进了一下,可以求输入日期以前最后一个符合要求的日期
  2. def isRunnian(year):
  3.     return year%400==0 or (year%4==0 and year%100!=0)

  4. def getThatDay(yearNow,monthNow,dayNow):
  5.     for year in range(yearNow,1000,-1):   #1988,1989,1990-1999,2000-2017都很显然不符合要求,本来可以不用循环的。
  6.         daysOfYear = [31,29,31,30,31,30,31,31,30,31,30,31] if isRunnian(year) else\
  7.                      [31,28,31,30,31,30,31,31,30,31,30,31]
  8.         for month  in range(12,0,-1):
  9.             for day in range(daysOfYear[month-1],0,-1):
  10.                 if len(set(str(year).zfill(4)+str(month).zfill(2)+str(day).zfill(2))) == 8 and\
  11.                    (year < yearNow or (year == yearNow and month < monthNow) or (year == yearNow and month == monthNow and day<=dayNow)):# 确保得到日期早于当日
  12.                     return str(year).zfill(4)+'-'+str(month).zfill(2)+'-'+str(day).zfill(2)

  13. print(getThatDay(2017,12,8))
  14. print(getThatDay(10000,12,31))
  15. print(getThatDay(1987,6,25))
  16. print(getThatDay(1900,12,31))


  17. ##    >>>
  18. ##    1987-06-25
  19. ##    9876-12-30
  20. ##    1987-06-25
  21. ##    1897-06-25
复制代码

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-7 23:51:03 | 显示全部楼层
  1. from itertools import permutations
  2. result = [''.join(i) for i in permutations('0123456789',8)]
  3. r = [i for i in result if int(i[-2:])<32 and int(i[-4:-2])<13 and int(i[0])<2]
  4. print(r[-1])
复制代码

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励,效率有点低^_^

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 00:47:12 | 显示全部楼层
本帖最后由 lihw 于 2017-12-8 08:05 编辑

xuei
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2017-12-8 10:58:14 | 显示全部楼层
排序,是不是答案不止一个呀?

点评

答案是唯一的,因为有这个条件“从自己的生日以后,一直到今天就再也没有出现这样的日期了”  发表于 2017-12-8 10:59
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 11:39:58 | 显示全部楼层
kent_allen 发表于 2017-12-7 23:19
得到好多个答案,因为“从自己的生日以后,一直到今天就再也没有出现这样的日期了。” 好些符 ...

19860524
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 11:40:32 | 显示全部楼层
kent_allen 发表于 2017-12-7 23:19
得到好多个答案,因为“从自己的生日以后,一直到今天就再也没有出现这样的日期了。” 好些符 ...

我应该是思路错了...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 12:23:11 | 显示全部楼层
  1. t = 20171207
  2. while t:
  3.     if len(set(str(t))) == 8 and int(str(t)[-4:-2]) < 12 and int(str(t)[-2:]) < 32:
  4.         print(t)
  5.         break
  6.     t -= 1
复制代码

这样写的效率比上面要高,上面运行2s左右,下面0.35s左右。
但是当t=23171207的时候(下一次出现这样的数会是2345年),运行会达到3.9s左右。
当然这个t是逐减一,应该还能简洁一下。
===================
下面是有单独针对这个题的,目前发现最快。
主要根据1yyy0m2d只有这样符合
  1. def func():
  2.     result = []
  3.     for i in range(2000,1000,-1):
  4.         for j in range(9,1,-1):
  5.             for g in range(31,20,-1):
  6.                 r = str(i)+'0'+str(j)+str(g)
  7.                 if len(set(r)) == 8:
  8.                     result.append(r)
  9.     return result[0]
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 13:02:57 | 显示全部楼层
  1. def check(day):
  2.     num = []
  3.     for i in range(4):
  4.         num.append(day[0] % 10)
  5.         day[0] //= 10
  6.     for i in range(2):
  7.         num.append(day[1] % 10)
  8.         day[1] //= 10
  9.     for i in range(2):
  10.         num.append(day[2] % 10)
  11.         day[2] //= 10
  12.     num.sort()
  13.     if num[0] != num[1] != num[2] != num[3] != num[4] != num[5] != num[6] != num[7]:
  14.         return True
  15.     else:
  16.         return False
  17. def yestoday(today):
  18.     if today[2] != 1:
  19.         today[2] -= 1
  20.     elif (today[1] in [2, 4, 6, 8, 9, 11]) == True:
  21.         today[2] = 31
  22.         today[1] -= 1
  23.     elif (today[1] in [5, 7, 10, 12]) == True:
  24.         today[2] = 30
  25.         today[1] -= 1
  26.     elif today[1] == 1:
  27.         today[2] = 31
  28.         today[1] = 12
  29.         today[0] -= 1
  30.     else:
  31.         if (((today[0] % 400) ==0) or (((today[0] % 100) != 0) and ((today[0] % 4) == 0))) == True:
  32.             today[2] = 29
  33.         else:
  34.             today[2] = 28
  35.         today[1] = 2
  36.     return today

  37. day = [2017, 12, 7]
  38. birthday = day[:]
  39. while True:
  40.     result = check(birthday)
  41.     if result == True:
  42.         break
  43.     else:
  44.         day = yestoday(day)
  45.         birthday = day[:]
  46. print('小明的生日是%d年%d月%d日' % (day[0], day[1], day[2]))
复制代码

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 14:24:07 | 显示全部楼层
  1. import datetime
  2. n=0
  3. while 1:
  4.     now=datetime.datetime.now()-datetime.timedelta(days=n)
  5.     a=now.strftime('%Y%m%d')  
  6.     if len(set(a))==8:
  7.         print('小明的生日为{}'.format(a))
  8.         break
  9.     n+=1
复制代码

我的另外一个想法:能够组成月的十位数只能是01,能够组成日的的十位数0123,所以必须其中0123必然会被使用掉2个数字。然后因为年的千位只能由12组成,所以12也必须使用在千位上
经过排列组合计算得出
1 0 2
1 0 3
2 0 1
2 0 3
2 1 0
2 1 3
然后计算年的百位,当年千位为2的时候年的百位只能为0,所以直接排除其他月和日的有0的排列组合。同时也排除了日的个位数为0的可能性
1 0 2
1 0 3
2 1 3
继续 日的十位数为3的时候其他位数不能为1。所以所有后只能得出1 0 2
这一个排列组合,那么最终的结果就是年千位等于1,月十位等于0,日十位等于2组成的一个其他位数不重复的数字。
不知道是不是偷懒的算法
  1. l=('9','8','7','6','5','4')
  2. a=['1','2']
  3. b=['0','1']
  4. c=['0','1','2','3']
  5. for y in a:
  6.     for m in b:
  7.         for d in c:
  8.             if d != m and d != y and m !=y:
  9.                 if (y == '2' and d !='0' and  m !='0' and d !='3' ) or (y=='1' and d != '3'):
  10.                     print(y+l[0]+l[1]+l[2]+m+l[3]+d+l[4])
复制代码

评分

参与人数 1荣誉 +3 鱼币 +3 贡献 +3 收起 理由
jerryxjr1220 + 3 + 3 + 3 答题奖励,其实不用编程也能推理出来

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 17:27:38 | 显示全部楼层
  1. list5=[]
  2. list1=[]
  3. list2=[]
  4. list3=[]
  5. list4=[]
  6. for year in range (1900,2018):
  7.    
  8.         if len ((str(year))) ==len(set(str(year))):
  9.             
  10.             list1.append(str(year))
  11.             

  12.         
  13. for mud in range (101,1231):
  14.         if len ((str(mud))) ==len(set(str(mud))):
  15.                 list2.append(str(mud))

  16.         
  17. for nu in list2:
  18.         if len(str(nu))==3:
  19.                 for j in range (3):
  20.                         if str(0) in nu[j]:
  21.                                list3.append(nu)

  22. for i in list3:
  23.         list2.remove(i)
  24. for j in range(len(list2)):
  25.         if len(list2[j])==3:
  26.                 list2[j]=str(0)+str(list2[j])
  27. for t in list2:
  28.         if t[2] <= str(3):
  29.                 if t[2]<=str(2):
  30.                         list4.append(t)
  31.                 if t[2]==str(3) and t[3] <=str(1):
  32.                         list4.append(t)
  33.                
  34.                         
  35. for i in list1:
  36.         for j in list4:
  37.                  if len(str(i)+str(j)) == len(set(str(i)+str(j))):
  38.                          list5.append(str(i)+str(j))
  39.                          list5.sort()
  40.                              
  41.                               
  42. print(list5[-1])               
复制代码

19870625

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 17:32:44 | 显示全部楼层
这个是一边想一边写的, 思路有点凌乱, 总体就是先比较年份, 把单个的年份看成一个数列,比较他数列的长度和集合的长度, 如果相同 就是没有重复的数字, 然后是月和日连在一起相同的方法比较, 但是要在个位数的月份前添加0, 最后把两个列表和在一起按照相同的方法比较, 这里没有考虑大月小月, 2月, 和闰月, 需要进一步的完善, 但是能算出结果。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 18:58:40 | 显示全部楼层
本帖最后由 solomonxian 于 2017-12-8 21:26 编辑

出这题的点不是在日期上吗···
为什么要给个工具绕过去
  1. def is_leap_feb(y, m):
  2.     return 1 if ((not y%4 and y%100) or not y%400) and m == 2 else 0
  3.    
  4. def fun(n):
  5.     data = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
  6.     return sorted((i*10000 + j*100 + k for i in range(123, n//10000)
  7.                   for j in range(1, 13)
  8.                   for k in range(1, data[j - 1] + is_leap_feb(i, j) + 1)
  9.                   if len(set(('0' + str(i*10000 + j*100 + k))[-8:])) == 8),
  10.                   key=lambda x: (x - n) % n)[-1]

  11. print(fun(20171208))
复制代码

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-8 20:10:50 | 显示全部楼层
  1. from datetime import date, timedelta

  2. def daterange(begin, end):
  3.     while 1:
  4.         yield begin
  5.         begin -= timedelta(days=1)

  6. for d in daterange(date.today(),date.min):
  7.     if len(d.strftime('%Y%m%d')) == len(set(d.strftime('%Y%m%d'))):
  8.         print(d)
  9.         break

复制代码


1987-06-25

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2017-12-9 10:57:08 | 显示全部楼层
now = datetime.date.today()#今天
gridday = datetime.timedelta(days=20000)#n天以前
past = now - gridday#n天以前的日期是多少
a = []
for i in range(20000):

    if len(str(past))-1 == len(set(str(past))):
        a.append(past)
        oneday = datetime.timedelta(1)
        past += oneday
    else:
        oneday = datetime.timedelta(1)
        past += oneday
print(a[-1])

评分

参与人数 1荣誉 +2 鱼币 +2 贡献 +2 收起 理由
jerryxjr1220 + 2 + 2 + 2 答题奖励

查看全部评分

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-3-29 14:06

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表