Welches Datum ist das nochmal?

10

Auf meiner Website geben Benutzer ihr Geburtsdatum im Stil ein xx.xx.xx- drei zweistellige Zahlen, die durch Punkte getrennt sind. Leider habe ich vergessen, den Benutzern genau mitzuteilen, welches Format sie verwenden sollen. Ich weiß nur, dass ein Abschnitt für den Monat, einer für das Datum und einer für das Jahr verwendet wird. Das Jahr liegt definitiv im 20. Jahrhundert (1900-1999), also 31.05.75bedeutet das Format 31 May 1975. Ich gehe auch davon aus, dass jeder entweder den Gregorianischen oder den Julianischen Kalender verwendet.

Jetzt möchte ich meine Datenbank durchsuchen, um das Chaos zu beseitigen. Ich möchte zunächst mit den Benutzern mit den mehrdeutigsten Daten umgehen, dh mit denen, bei denen der Bereich möglicher Daten am größten ist.

Zum Beispiel 08.27.53bedeutet das Datum 27 August 1953entweder im Gregorianischen oder im Julianischen Kalender. Das Datum im julianischen Kalender ist 13 Tage später, die Reichweite ist also gerecht 13 days.

Im Gegensatz dazu kann sich die Notation 01.05.12auf viele mögliche Daten beziehen. Das früheste ist 12 May 1901 (Gregorian)und das späteste ist 1 May 1912 (Julian). Die Reichweite beträgt 4020 days.

Regeln

  • Die Eingabe ist eine Zeichenfolge im Format xx.xx.xx, bei der jedes Feld zweistellig und mit Nullen aufgefüllt ist.
  • Die Ausgabe ist die Anzahl der Tage im Bereich.
  • Sie können davon ausgehen, dass die Eingabe immer ein gültiges Datum ist.
  • Sie dürfen keine integrierten Datums- oder Kalenderfunktionen verwenden.
  • Der kürzeste Code (in Bytes) gewinnt.

Testfälle

  • 01.00.31 => 12
  • 29.00.02=> 0(Die einzige Möglichkeit ist 29 February 1900 (Julian))
  • 04.30.00 => 13
  • 06.12.15 => 3291
Ypnypn
quelle
Soll das 5, May 1975sein 31st? Müssen wir auch Schaltjahre berücksichtigen?
Maltysen
@Maltysen Ja, behoben. Ja.
Ypnypn
Warum konnte es nicht im 21. Jahrhundert sein?
ElefantPhace
@ElefantPhace Die Regeln besagen, dass das 20. Jahrhundert angenommen wird; Andernfalls würde es kein maximales Datum geben.
Ypnypn

Antworten:

6

Pyth, 118 Bytes

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

Probieren Sie es online aus: Demonstration oder Test Suite .

Notwendige Kenntnisse der julianischen und gregorianischen Kalender

Julian und Gregorianischer Kalender sind ziemlich ähnlich. Jeder Kalender unterteilt ein Jahr in 12 Monate mit jeweils 28 bis 31 Tagen. Die genauen Tage in einem Monat sind [31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]. Der einzige Unterschied zwischen den Kalendern besteht in der Definition eines Schaltjahres. Im Julianischen Kalender ist jedes durch 4 teilbare Jahr ein Schaltjahr. Der Gregorianische Kalender ist etwas spezifischer. Jedes durch 4 teilbare Jahr ist ein Schaltjahr, mit Ausnahme des durch 100 teilbaren und nicht durch 400 teilbaren Jahres.

Im 20. Jahrhundert ist also nur ein Jahr anders. Das Jahr 1900, das im julianischen Kalender ein Schaltjahr ist, im gregorianischen Kalender jedoch kein Schaltjahr. Das einzige Datum, das in dem einen Kalender, aber nicht im anderen Kalender vorhanden ist, ist der Tag 29.02.1900.

Aufgrund der unterschiedlichen Schaltjahrdefinition gibt es einen Unterschied zwischen einem Datum im Julianischen Kalender und dem Gregorianischen Kalender. 12 Tage Unterschied für ein Datum vor dem 29.02.1900und 13 Tage Unterschied für Daten nach dem 29.02.1900.

Vereinfachter Pseudocode

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

Detaillierte Code-Erklärung

Der erste Teil M++28@j15973358 4G&qG2!%H4definiert eine Funktion g(G,H), die die Anzahl der Tage im Monat Geines Jahres Him Julianischen Kalender berechnet .

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)

Und der nächste Teil ist nur die for-Schleife und das ifs. Beachten Sie, dass ich Nim Format interpretiere (month, year, day). Nur weil es einige Bytes spart.

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))
Jakube
quelle
0

Perl 5 , 294 Bytes

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

Probieren Sie es online aus!

298 Bytes, wenn Leerzeichen, Zeilenumbrüche und Kommentare entfernt werden.

1-4 initialisiert Linien die (falls noch nicht geschehen) %gund %jHashes , wo die Werte den gregorianischen und julianischen Tag Zahlen entsprechend vom 1. Jaunary 1900 bis zu zählen bis 31. Dezember 1999.

Zeile 5 setzt das Eingabedatum in $ 1, $ 2 und $ 3.

Zeile 9 listet alle sechs Permutationen dieser drei Eingangsnummern auf.

Zeile 8 wandelt diese sechs in zwei Zahlen um, die gregorianische und die julianische Tageszahl, aber nur diejenigen, die gültige Daten sind.

Zeile 7 stellt sicher, dass nicht vorhandene Tageszahlen herausgefiltert werden.

Zeile 6 sortiert die Liste der gültigen Datumsnummern vom kleinsten zum größten.

Zeile 10 gibt dann die Differenz zwischen dem letzten und dem ersten (max und min) zurück, die der gewünschte Bereich war.

Kjetil S.
quelle