Quelle date est-ce encore?

10

Sur mon site Web, les utilisateurs saisissent leur date de naissance dans le style xx.xx.xx- trois nombres à deux chiffres séparés par des points. Malheureusement, j'ai oublié de dire aux utilisateurs quel format utiliser. Tout ce que je sais, c'est qu'une section est utilisée pour le mois, une pour la date et une pour l'année. L'année est définitivement au 20ème siècle (1900-1999), donc le format 31.05.75signifie 31 May 1975. En outre, je suppose que tout le monde utilise le calendrier grégorien ou julien.

Maintenant, je veux parcourir ma base de données pour nettoyer le gâchis. J'aimerais commencer par traiter avec les utilisateurs dont les dates sont les plus ambiguës, c'est-à-dire celles où la plage de dates possibles est la plus grande.

Par exemple, la date 08.27.53signifie 27 August 1953dans le calendrier grégorien ou julien. La date dans le calendrier julien est 13 jours plus tard, donc la plage est juste 13 days.

En revanche, la notation 01.05.12peut faire référence à de nombreuses dates possibles. Le premier est 12 May 1901 (Gregorian)le dernier 1 May 1912 (Julian). La plage est 4020 days.

Règles

  • L'entrée est une chaîne au format xx.xx.xx, où chaque champ est composé de deux chiffres et complété par un zéro.
  • La sortie est le nombre de jours dans la plage.
  • Vous pouvez supposer que l'entrée sera toujours une date valide.
  • Vous ne pouvez utiliser aucune fonction de date ou de calendrier intégrée.
  • Le code le plus court (en octets) gagne.

Cas de test

  • 01.00.31 => 12
  • 29.00.02=> 0(La seule possibilité est 29 February 1900 (Julian))
  • 04.30.00 => 13
  • 06.12.15 => 3291
Ypnypn
la source
Est-ce 5, May 1975censé l'être 31st? De plus, devons-nous tenir compte des années bissextiles?
Maltysen
@Maltysen Oui, corrigé. Oui.
Ypnypn
Pourquoi ne pourrait-il pas en être ainsi au 21e siècle?
ElefantPhace
@ElefantPhace Les règles stipulent que le 20e siècle est supposé; sinon, il n'y aurait pas de date maximale.
Ypnypn

Réponses:

6

Pyth, 118 octets

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

Essayez-le en ligne: démonstration ou suite de tests .

Connaissance nécessaire des calendriers julien et grégorien

Le calendrier julien et grégorien sont assez similaires. Chaque calendrier divise une année en 12 mois, chacun contenant de 28 à 31 jours. Les jours exacts d'un mois sont [31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]. La seule différence entre les calendriers est leur définition d'une année bissextile. Dans le calendrier julien, toute année divisible par 4 est une année bissextile. Le calendrier grégorien est un peu plus spécifique. Toute année divisible par 4 est une année bissextile, sauf l'année divisible par 100 et non divisible par 400.

Ainsi, au 20e siècle, une seule année est différente. L'année 1900, qui est une année bissextile dans le calendrier julien, mais pas une année bissextile dans le calendrier grégorien. Donc, la seule date qui existe dans un calendrier mais pas dans l'autre calendrier est le jour 29.02.1900.

En raison de la définition différente de l'année bissextile, il y a une différence entre une date dans le calendrier julien et le calendrier grégorien. Différence de 12 jours pour une date antérieure au 29.02.1900, et de 13 jours pour les dates postérieures au 29.02.1900.

Pseudo-code simplifié

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

Explication détaillée du code

La première partie M++28@j15973358 4G&qG2!%H4définit une fonction g(G,H), qui calcule le nombre de jours du mois Gd'une année Hdans le calendrier julien.

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)

Et la partie suivante est juste la boucle for et les ifs. Notez que j'interprète Ndans le format (month, year, day). Tout simplement parce qu'il enregistre quelques octets.

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
la source
0

Perl 5 , 294 octets

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

Essayez-le en ligne!

298 octets lorsque les espaces, les nouvelles lignes et les commentaires sont supprimés.

Les lignes 1 à 4 initialisent (si ce n'est pas fait) les hachages %get %joù les valeurs sont les nombres de jours grégorien et julien en conséquence, du 1er janvier 1900 au 31 décembre 1999.

La ligne 5 met la date d'entrée en $ 1, $ 2 et $ 3.

La ligne 9 répertorie les six permutations de ces trois numéros d'entrée.

La ligne 8 convertit ces six en deux nombres chacun, les nombres grégorien et julien, mais uniquement ceux qui sont des dates valides.

La ligne 7 s'en assure, elle filtre les numéros de jour inexistants.

La ligne 6 trie la liste des numéros de date valides du plus petit au plus grand.

La ligne 10 renvoie alors la différence entre le dernier et le premier (max et min), qui était la plage souhaitée.

Kjetil S.
la source