jerryxjr1220 发表于 2017-12-7 20:53:59

Python:每日一题 130

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

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

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


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

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

tailor_long 发表于 2017-12-7 21:08:56

贫穷限制了我的想象!!!
不知小明同学可以活多久?
不知“再也没有出现过这样的日期”中的“这样”是哪种程度的“这样”?
{:10_266:}

wyp02033 发表于 2017-12-7 21:59:41

本帖最后由 wyp02033 于 2017-12-7 22:02 编辑

from time import perf_counter

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

def find_the_birthday():
    year = 2017
    months =
    days =
    i = 11
    while True:
      for day in range(days, 0, -1):
            birthday = str(year) + "%02d" % months + "%02d" % day         
            if len(set(birthday)) == len(birthday):
                return birthday
      i -= 1

      if i < 0:
            year -= 1
            i = 11
            if is_leap_year(year):
                days = 29

if __name__ == '__main__':
    start = perf_counter()
    print(find_the_birthday())
    end = perf_counter()
    print("time uesd:", end - start)
19870625
time uesd: 0.012000967581096625

亭ting 发表于 2017-12-7 22:01:44

结果是:19870625    即1987年6月25日
stor=[]
for d1 in range(10):
    for d2 in range(10):
      if d1!=d2:
            for d3 in range(10):
                if (d1!=d3)&(d2!=d3):
                  for d4 in range(10):
                        if(d1!=d4)&(d2!=d4)&(d3!=d4):
                            for d5 in range(10):
                              if(d1!=d5)&(d2!=d5)&(d3!=d5)&(d4!=d5):
                                    for d6 in range(10):
                                        if(d1!=d6)&(d2!=d6)&(d3!=d6)&(d4!=d6)&(d5!=d6):
                                          for d7 in range(10):
                                                if(d1!=d7)&(d2!=d7)&(d3!=d7)&(d4!=d7)&(d5!=d7)&(d6!=d7):
                                                    for d8 in range(10):
                                                      if(d1!=d8)&(d2!=d8)&(d3!=d8)&(d4!=d8)&(d5!=d8)&(d6!=d8)&(d7!=d8):
                                                            data=d1+d2*10+d3*100+d4*1000+d5*10000+d6*100000+d7*1000000+d8*10000000
                                                            day=d1+d2*10
                                                            month=d3+d4*10
                                                            if (month in {1,3,5,7,8,10,12})&(data <=20171207)&(day<=31):
                                                                stor.append(data)
                                                            if (month in {4,6,11})&(data <=20171207)&(day<=30):
                                                                stor.append(data)
                                                   
                                                            if (data <=20171207)&(day<=29)&(month==2):
                                                                stor.append(data)
                                                            

print max(stor)

小宏~ 发表于 2017-12-7 22:49:23

本帖最后由 小宏~ 于 2017-12-7 22:51 编辑

print("+++++++++小宏最帅+++++++\n")
a={1:0,2:0,3:0,4:0,5:0,6:0,7:0,8:0}
m=2017
count=0
#假设小明在100岁之内
for i in range(100):
n=int(m-i)
a=(n//1000)
a=(n%1000//100)
a=(n%100//10)
a=(n%10)
for j in range(1,13):
    a=(j//10)
    a=(j%10)
    for x in range(1,32):
      a=(x//10)
      a=(x%10)
      for i in range(1,9):
      for j in range(i+1,9):
          if(a!=a):
            count=count+1
      if(count==28):
      print("他的生日是:%d %d %d %d年 %d %d月 %d %d日" %(a,a,a,a,a,a,a,a))
      exit()
      count=0
      

kent_allen 发表于 2017-12-7 23:19:12

{:10_269:}得到好多个答案,因为“从自己的生日以后,一直到今天就再也没有出现这样的日期了。” 好些符合这句话的答案,让老师见笑了。期待看到精选答案~

我的程序如下:

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)

shigure_takimi 发表于 2017-12-7 23:34:44

本帖最后由 shigure_takimi 于 2017-12-8 08:44 编辑

def isRunnian(year):
    return year%400==0 or (year%4==0 and year%100!=0)

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

print(getThatDay())


##    >>>
##    1987-06-25


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

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

print(getThatDay(2017,12,8))
print(getThatDay(10000,12,31))
print(getThatDay(1987,6,25))
print(getThatDay(1900,12,31))


##    >>>
##    1987-06-25
##    9876-12-30
##    1987-06-25
##    1897-06-25

bush牛 发表于 2017-12-7 23:51:03

from itertools import permutations
result = [''.join(i) for i in permutations('0123456789',8)]
r = )<32 and int(i[-4:-2])<13 and int(i)<2]
print(r[-1])

lihw 发表于 2017-12-8 00:47:12

本帖最后由 lihw 于 2017-12-8 08:05 编辑

xuei

215330 发表于 2017-12-8 10:58:14

排序,是不是答案不止一个呀?

kent_allen 发表于 2017-12-8 11:39:58

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

19860524

kent_allen 发表于 2017-12-8 11:40:32

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

我应该是思路错了...

bush牛 发表于 2017-12-8 12:23:11

bush牛 发表于 2017-12-7 23:51


t = 20171207
while t:
    if len(set(str(t))) == 8 and int(str(t)[-4:-2]) < 12 and int(str(t)[-2:]) < 32:
      print(t)
      break
    t -= 1
这样写的效率比上面要高,上面运行2s左右,下面0.35s左右。
但是当t=23171207的时候(下一次出现这样的数会是2345年),运行会达到3.9s左右。
当然这个t是逐减一,应该还能简洁一下。
===================
下面是有单独针对这个题的,目前发现最快。
主要根据1yyy0m2d只有这样符合
def func():
    result = []
    for i in range(2000,1000,-1):
      for j in range(9,1,-1):
            for g in range(31,20,-1):
                r = str(i)+'0'+str(j)+str(g)
                if len(set(r)) == 8:
                  result.append(r)
    return result

Bill888 发表于 2017-12-8 13:02:57

def check(day):
    num = []
    for i in range(4):
      num.append(day % 10)
      day //= 10
    for i in range(2):
      num.append(day % 10)
      day //= 10
    for i in range(2):
      num.append(day % 10)
      day //= 10
    num.sort()
    if num != num != num != num != num != num != num != num:
      return True
    else:
      return False
def yestoday(today):
    if today != 1:
      today -= 1
    elif (today in ) == True:
      today = 31
      today -= 1
    elif (today in ) == True:
      today = 30
      today -= 1
    elif today == 1:
      today = 31
      today = 12
      today -= 1
    else:
      if (((today % 400) ==0) or (((today % 100) != 0) and ((today % 4) == 0))) == True:
            today = 29
      else:
            today = 28
      today = 2
    return today

day =
birthday = day[:]
while True:
    result = check(birthday)
    if result == True:
      break
    else:
      day = yestoday(day)
      birthday = day[:]
print('小明的生日是%d年%d月%d日' % (day, day, day))

colinshi 发表于 2017-12-8 14:24:07

import datetime
n=0
while 1:
    now=datetime.datetime.now()-datetime.timedelta(days=n)
    a=now.strftime('%Y%m%d')
    if len(set(a))==8:
      print('小明的生日为{}'.format(a))
      break
    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组成的一个其他位数不重复的数字。
不知道是不是偷懒的算法
l=('9','8','7','6','5','4')
a=['1','2']
b=['0','1']
c=['0','1','2','3']
for y in a:
    for m in b:
      for d in c:
            if d != m and d != y and m !=y:
                if (y == '2' and d !='0' andm !='0' and d !='3' ) or (y=='1' and d != '3'):
                  print(y+l+l+l+m+l+d+l)

lihw 发表于 2017-12-8 17:27:38

list5=[]
list1=[]
list2=[]
list3=[]
list4=[]
for year in range (1900,2018):
   
      if len ((str(year))) ==len(set(str(year))):
            
            list1.append(str(year))
            

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

      
for nu in list2:
      if len(str(nu))==3:
                for j in range (3):
                        if str(0) in nu:
                               list3.append(nu)

for i in list3:
      list2.remove(i)
for j in range(len(list2)):
      if len(list2)==3:
                list2=str(0)+str(list2)
for t in list2:
      if t <= str(3):
                if t<=str(2):
                        list4.append(t)
                if t==str(3) and t <=str(1):
                        list4.append(t)
               
                        
for i in list1:
      for j in list4:
               if len(str(i)+str(j)) == len(set(str(i)+str(j))):
                         list5.append(str(i)+str(j))
                         list5.sort()
                           
                              
print(list5[-1])               

19870625

lihw 发表于 2017-12-8 17:32:44

这个是一边想一边写的, 思路有点凌乱, 总体就是先比较年份, 把单个的年份看成一个数列,比较他数列的长度和集合的长度, 如果相同 就是没有重复的数字, 然后是月和日连在一起相同的方法比较, 但是要在个位数的月份前添加0, 最后把两个列表和在一起按照相同的方法比较, 这里没有考虑大月小月, 2月, 和闰月, 需要进一步的完善, 但是能算出结果。

solomonxian 发表于 2017-12-8 18:58:40

本帖最后由 solomonxian 于 2017-12-8 21:26 编辑

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

print(fun(20171208))

Elastcio 发表于 2017-12-8 20:10:50

from datetime import date, timedelta

def daterange(begin, end):
    while 1:
      yield begin
      begin -= timedelta(days=1)

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



1987-06-25

sunnychou 发表于 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
查看完整版本: Python:每日一题 130