Che data è quella di nuovo?


10

Sul mio sito Web, gli utenti inseriscono la loro data di nascita nello stile xx.xx.xx: tre numeri a due cifre separati da punti. Sfortunatamente, ho dimenticato di dire agli utenti esattamente quale formato utilizzare. Tutto quello che so è che una sezione viene utilizzata per il mese, una per la data e una per l'anno. L'anno è sicuramente nel 20 ° secolo (1900-1999), quindi il formato 31.05.75significa 31 May 1975. Inoltre, presumo che tutti usino il calendario gregoriano o giuliano.

Ora, voglio passare attraverso il mio database per cancellare il pasticcio. Vorrei iniziare trattando con gli utenti le date più ambigue, ovvero quelle in cui l'intervallo di date possibili è il più grande.

Ad esempio, la data 08.27.53indica 27 August 1953nel calendario gregoriano o giuliano. La data nel calendario giuliano è 13 giorni dopo, quindi l'intervallo è giusto 13 days.

Al contrario, la notazione 01.05.12può riferirsi a molte date possibili. Il primo è 12 May 1901 (Gregorian)e l'ultimo è 1 May 1912 (Julian). La gamma è 4020 days.

Regole

  • L'input è una stringa nel formato xx.xx.xx, in cui ogni campo è composto da due cifre e con zero.
  • L'output è il numero di giorni nell'intervallo.
  • Si può presumere che l'input sarà sempre una data valida.
  • Non è possibile utilizzare alcuna data incorporata o funzioni del calendario.
  • Il codice più breve (in byte) vince.

Casi test

  • 01.00.31 => 12
  • 29.00.02=> 0(L'unica possibilità è 29 February 1900 (Julian))
  • 04.30.00 => 13
  • 06.12.15 => 3291

È il 5, May 1975supposto per essere 31st? Inoltre, dobbiamo tenere conto degli anni bisestili?
Maltysen,

@Maltysen Sì, risolto. Sì.
Ypnypn,

Perché non potrebbe essere nel 21 ° secolo?
ElefantPhace,

@ElefantPhace Le regole affermano che il 20 ° secolo è assunto; altrimenti non ci sarebbe una data massima.
Ypnypn,

Risposte:


6

Pyth, 118 byte

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

Provalo online: dimostrazione o Test Suite .

Conoscenza necessaria dei calendari giuliano e gregoriano

Il calendario giuliano e gregoriano sono abbastanza simili. Ogni calendario divide un anno in 12 mesi, ciascuno contenente da 28 a 31 giorni. I giorni esatti in un mese sono [31, 28/29 (depends on leap year), 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]. L'unica differenza tra i calendari è la loro definizione di un anno bisestile. Nel calendario giuliano ogni anno divisibile per 4 è un anno bisestile. Il calendario gregoriano è un po 'più specifico. Ogni anno divisibile per 4 è un anno bisestile, tranne l'anno divisibile per 100 e non divisibile per 400.

Quindi nel 20 ° secolo solo un anno è diverso. L'anno 1900, che è un anno bisestile nel Calendario giuliano, ma non un anno bisestile nel Calendario gregoriano. Quindi l'unica data, che esiste in un calendario ma non nell'altro calendario è il giorno 29.02.1900.

A causa della diversa definizione dell'anno bisestile, c'è una differenza tra una data nel calendario giuliano e il calendario gregoriano. 12 giorni di differenza per una data prima del 29.02.1900e 13 giorni di differenza per le date successive al 29.02.1900.

Pseudo-codice semplificato

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

Spiegazione dettagliata del codice

La prima parte M++28@j15973358 4G&qG2!%H4definisce una funzione g(G,H), che calcola il numero di giorni nel mese Gdi un anno Hnel calendario giuliano.

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)

E la parte successiva è solo il ciclo for e gli if. Si noti che interpreto Nnel formato (month, year, day). Solo perché salva alcuni byte.

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 byte

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

Provalo online!

298 byte quando vengono rimossi spazi, righe e commenti.

Le righe 1-4 inizializzano (se non si eseguono) gli hash %ge %jdove i valori sono i numeri dei giorni gregoriano e giuliano che contano di conseguenza dal 1 ° giugno 1900 al 31 dicembre 1999.

La riga 5 inserisce la data di input in $ 1, $ 2 e $ 3.

La riga 9 elenca tutte e sei le permutazioni di quei tre numeri di input.

La riga 8 converte quei sei in due numeri ciascuno, i numeri dei giorni gregoriano e giuliano, ma solo quelli che sono date valide.

La riga 7 lo assicura, filtra i numeri dei giorni inesistenti.

La riga 6 ordina l'elenco dei numeri di data validi dal più piccolo al più grande.

La riga 10 restituisce quindi la differenza tra l'ultimo e il primo (massimo e minimo), che era l'intervallo desiderato.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.