また何日ですか?


10

私のウェブサイトでは、ユーザーは生年月日をスタイルで入力しますxx.xx.xx-ドットで区切られた3つの2桁の数字。残念ながら、使用する形式をユーザーに正確に伝えるのを忘れていました。私が知っているのは、1つのセクションが月、1つが日付、1つが年に使用されることだけです。年は間違いなく20世紀(1900-1999)であるため、形式31.05.75はを意味し31 May 1975ます。また、誰もがグレゴリオ暦またはユリウス暦のどちらかを使用していると想定しています。

ここで、データベースを調べて混乱を解消したいと思います。最初に、日付が最も曖昧な、つまり可能な日付の範囲が最も広いユーザーに対処します。

たとえば、日付08.27.5327 August 1953グレゴリオ暦またはユリウス暦のどちらかを意味します。ユリウス暦の日付は13日後なので、範囲はちょうど13 daysです。

対照的に、表記01.05.12は多くの可能な日付を参照できます。最古は12 May 1901 (Gregorian)、最新は1 May 1912 (Julian)です。範囲は4020 daysです。

ルール

  • 入力はの形式の文字列で、xx.xx.xx各フィールドは2桁でゼロが埋め込まれます。
  • 出力は範囲内の日数です。
  • 入力は常に有効な日付であると想定できます。
  • 組み込みの日付またはカレンダー関数を使用することはできません。
  • 最短コード(バイト単位)が優先されます。

テストケース

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

される5, May 1975ことになって31st?また、うるう年を考慮する必要がありますか?
マルティセン

@Maltysenはい、修正されました。はい。
Ypnypn 2015年

21世紀にならないのはなぜですか。
ElefantPhace

@ElefantPhaceルールでは、20世紀を想定しています。それ以外の場合、最大日付はありません。
Ypnypn

回答:


6

Pyth、118バイト

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

オンラインでお試しください:デモまたはテストスイート

ユリウス暦とグレゴリオ暦の必要な知識

ユリウス暦とグレゴリオ暦はよく似ています。各カレンダーは、1年を12か月に分割し、それぞれに28〜31日が含まれます。月の正確な日数は[31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]です。カレンダー間の唯一の違いは、うるう年の定義です。ユリウス暦では、4で割り切れる年はうるう年です。グレゴリオ暦はもう少し具体的です。4で割り切れる年はうるう年です。ただし、100で割り切れる年は400で割り切れません。

したがって、20世紀では1年しか異なりません。1900年。ユリウス暦ではうるう年ですが、グレゴリオ暦ではうるう年ではありません。つまり、一方のカレンダーには存在するが、他方のカレンダーには存在しない唯一の日付は日29.02.1900です。

うるう年の定義が異なるため、ユリウス暦とグレゴリオ暦の日付には違いがあります。の前の日付の場合は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行目は、これら3つの入力数値の6つの順列すべてをリストしています。

8行目では、これらの6つをそれぞれグレゴリオ暦とユリウス暦の2つの数値に変換していますが、有効な日付の数値のみです。

行7はそれを確認し、存在しない日数を除外します。

6行目は、有効な日付番号のリストを最小から最大に並べ替えます。

10行目は、最後と最初の差(最大と最小)を返します。これは、必要な範囲でした。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.