那又是几号?


10

在我的网站上,用户使用以下格式输入出生日期xx.xx.xx-用点分隔的三个两位数字。不幸的是,我忘了告诉用户确切使用哪种格式。我所知道的是,一个部分用于月份,一个部分用于日期,另一部分用于年份。绝对是20世纪(1900-1999),因此格式31.05.7531 May 1975。另外,我假设每个人都使用公历或儒略历。

现在,我想浏览数据库以清除混乱情况。首先,我想与日期最不明确的用户打交道,即那些可能的日期范围最大的用户。

例如,日期08.27.53表示27 August 1953公历或儒略历。朱利安日历中的日期是13天后,因此范围是13 days

相反,该符号01.05.12可以指代许多可能的日期。最早的是12 May 1901 (Gregorian),最新的是1 May 1912 (Julian)。范围是4020 days

规则

  • 输入是格式为的字符串xx.xx.xx,其中每个字段均为两位数字,并用零填充。
  • 输出是该范围内的天数。
  • 您可以假定输入将始终是有效日期。
  • 您不得使用任何内置的日期或日历功能。
  • 最短的代码(以字节为单位)获胜。

测试用例

  • 01.00.31 => 12
  • 29.00.02=> 0(唯一的可能性是29 February 1900 (Julian)
  • 04.30.00 => 13
  • 06.12.15 => 3291

5, May 1975应该31st?另外,我们是否必须考虑leap年?
Maltysen,2015年

@Maltysen是的,已修复。是。
Ypnypn

为什么不能在21世纪?
ElefantPhace 2015年

@ ElefantPhace规则规定假定20世纪。否则将没有最大日期。
Ypnypn 2015年

Answers:


6

Pyth,118个字节

M++28@j15973358 4G&qG2!%H4FN.pmv>dqhd\0cz\.I&&&hN<hN13eN<eNhgFPNaYK+++*365JhtN/+3J4smghdJthNeNInK60aY-K+12>K60;-eSYhSY

在线尝试:演示测试套件

儒略历和公历的必要知识

朱利安日历和公历非常相似。每个日历将一年分为12个月,每个月包含28-31天。一个月中的确切日期是[31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]。日历之间的唯一区别是它们对a年的定义。在儒略历中,任何可以被4整除的年份都是year年。公历较为具体。可以除以4的任何年份都是a年,除了可以除以100且不能除以400的年份。

因此,在20世纪只有一年不同。1900年,在儒略历中是a年,但在公历中不是not年。因此,一个日历中存在但另一个日历中不存在的唯一日期是日期29.02.1900

由于leap年的定义不同,因此儒略历和公历之间的日期有所不同。之前的日期相差12天,之后的日期29.02.1900相差13天29.02.1900

简化的伪代码

Y = []  # empty list
for each permutation N of the input date:
   if N is valid in the Julian Calendar:
      K = number of days since 0.01.1900
      append K to Y
      if K != 60:  # 60 would be the 29.02.1900
         L = K - (12 if K < 60 else 13) 
         append L to Y
print the difference between the largest and smallest value in Y

详细代码说明

第一部分M++28@j15973358 4G&qG2!%H4定义一个函数g(G,H),该函数计算儒略历中G一年H中某月的天数。

M                            def g(G,H): return
      j15973358 4               convert 15973358 into base 4
     @           G              take the Gth element
  +28                           + 28
 +                &qG2!%H4      + (G == 2 and not H % 4)

下一部分只是for循环和ifs。请注意,我以N格式进行解释(month, year, day)。只是因为它节省了一些字节。

FN.pmv>dqhd\0cz\.
             cz\.        split input by "."
    mv>dqhd\0            map each d of ^ to: eval(d[d[0]=="0":])
FN.p                     for N in permutations(^):

I&&&hN<hN13eN<eNhgFPN   
I                          if 
    hN                        month != 0
   &                          and
      <hN13                   month < 13
  &                           and
           eN                 day != 0
 &                            and
             <eNhgFPN         day < 1 + g(month,year):

aYK+++*365JhtN/+3J4smghdJthNeN
          JhtN                    J = year
     +*365J   /+3J4               J*365 + (3 + J)/4
    +              smghdJthN      + sum(g(1+d,year) for d in [0, 1, ... month-2])
   +                        eN    + day
  K                               K = ^
aYK                               append K to Y

InK60aY-K+12>K60            
InK60                             if K != 60:
     aY-K+12>K60                    append K - (12 + (K > 60)) to Y

;-eSYhSY
;          end for loop
 -eSYhSY   print end(sorted(Y)) - head(sorted(Y))

0

Perl 5,294个字节

sub f{map/(\d\d)(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])/             #1             
      &&$3<29+($2==2?!($1%4):2+($2/.88)%2)                        #2  
      &&($j{$_}=++$j+12)                                          #3
      &&$j!#1=60?$g{$_}=++$g:0,'000101'..'991231'if!%g;           #4
      pop=~/(\d\d).(\d\d).(\d\d)/;                                #5
      @n=sort{$a<=>$b}                                            #6
         grep$_,                                                  #7
         map{($j{$_},$g{$_})}                                     #8
         ("$1$2$3","$1$3$2","$2$1$3","$2$3$1","$3$1$2","$3$2$1"); #9
      $n[-1]-$n[0]}                                               #10

在线尝试!

删除空格,换行符和注释时为298个字节。

第1-4行初始化(如果未完成)%g%j哈希值,其值分别是从1900年1月1日到1999年12月31日的公历和儒略日数。

第5行将输入日期放入$ 1,$ 2和$ 3。

第9行列出了这三个输入数字的所有六个排列。

第8行将这六个数字分别转换为两个数字,格里高利和朱利安天数,但只有那些有效日期。

第7行确保了这一点,它过滤掉了不存在的日期数字。

第6行从最小到最大对有效日期数字列表进行排序。

第10行返回最后一个和第一个(最大和最小)之间的差,这就是所需范围。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.