Allora siamo ancora?


22

Sono un viaggiatore nel tempo e sono ossessionato dal passare del tempo. Adoro particolarmente i momenti in cui le lancette dell'orologio passano 12, o quando riesco a passare alla pagina successiva del mio calendario, o quando tutti urlano "Felice Anno Nuovo!"

Per favore, scrivi per me un programma per mostrarmi quanto sono lontano dall'ultimo momento al successivo, sotto forma di una barra di avanzamento. Ad esempio, se gli dico che l'ora è 09:12, dovrebbe stampare questo:

09:00 ####---------------- 10:00

Se gli dico che il mese è maggio 1982, dovrebbe stampare questo:

1982-01 #######------------- 1983-01

Ho già detto che sono un viaggiatore nel tempo? Viaggio ovunque dal primo millisecondo di 0 d.C. all'ultimo millisecondo di 9999 d.C., quindi il programma deve gestire qualsiasi data e ora in quell'intervallo.

Ingresso

  • L'input sarà in uno dei seguenti formati:

    • YYYY-MM-DDThh:mm:ss.sss
    • YYYY-MM-DDThh:mm:ss
    • YYYY-MM-DDThh:mm
    • YYYY-MM-DDThh
    • YYYY-MM-DD
    • YYYY-MM

    Questi sono gli unici formati che devono essere gestiti. Ogni parte avrà esattamente il numero di cifre mostrate, il che significa che i secondi frazionari possono avere zero finali (ad esempio .120, mai .12). Il Tè una lettera letterale "T" che delimita la data dal tempo. Le ore sono su un orologio di 24 ore.

  • Mesi e giorni sono basati su 1 (di più su questo di seguito).

  • Non è necessario gestire input non validi e fuori portata.

  • A discrezione del programmatore, l'input può avere una sola nuova riga finale.

Barra di avanzamento matematica

Il programma riguarda le unità meno significative e le seconde meno significative nel dato input. Ad esempio, se l'input ha una precisione a livello di giorno (ad es. 2016-12-14), La barra di avanzamento indicherà la percentuale di giorni trascorsi nel mese di input rispetto a ciò che rimane.

La barra di avanzamento avrà 20 unità (caratteri) e la proporzione rappresentata sarà arrotondata all'incremento più vicino di 120 . Ad esempio, dato che 2016-12-14T12:28la barra di avanzamento mostrerà Round ( 2860 × 20) = 9 di 20 unità "riempite".

1 mese e giorni

Sebbene il giorno del 1 ° dicembre (per esempio) sia 01inserito 2016-12-01, ai fini del calcolo è il 0 ° giorno del mese, poiché le unità troncate implicano il 0o millisecondo del 0o minuto dell'ora 0 del giorno. In altre parole, 2016-12-01è 031 del modo fino a dicembre ed 2016-12-02è 131 e così via.

Allo stesso modo, 2016-01è il 0 ° millisecondo del 0 ° giorno di gennaio, quindi nei calcoli è 012 , il che significa che 2016-12è 1112 .

Sì, ciò significa che mesi e giorni non riempiranno mai completamente la barra di avanzamento.

Durata del mese e anni bisestili diversi

Mesi diversi hanno numeri di giorni diversi e l'output deve riflettere questo, inclusi gli anni bisestili. La barra di avanzamento per il 6 febbraio 2017 sarà diversa dalla barra di avanzamento per il 6 febbraio 2016 (o il 6 gennaio di entrambi gli anni).

miscellaneo

  • I viaggiatori del tempo usano il proletico calendario gregoriano . TL; DR: nessun caso speciale come giorni mancanti nel 1752 . L'input includerà le date nell'anno 0 d.C.
  • I viaggiatori del tempo ignorano l'ora legale.
  • Non è necessario che il programma tenga conto dei secondi intercalari, ma potrebbe esserlo.

Produzione

Il programma (o la funzione) deve stampare (o restituire come stringa) una barra di avanzamento di 20 caratteri orientata orizzontalmente che viene "riempita" per il tempo trascorso e "aperta" per il tempo rimanente. Deve "compilare" da sinistra a destra.

La barra di avanzamento deve avere un'etichetta alla sua sinistra che mostra l'inizio del periodo da contare e un'altra alla sua destra che mostra l'inizio del periodo successivo, nello stesso formato dell'input (ma che mostra solo due unità di precisione). Per il nostro esempio un 2016-12-14output valido sarebbe:

12-01 #########----------- 01-01

Ecco i formati di etichetta validi per ciascuno dei periodi possibili:

  • mesi: YYYY-MM
  • giorni: MM-DD
  • Ore: DDThh
  • Minuti: hh:mm
  • secondi: mm:ss
  • millisecondi: ss.sss

Nessuna unità aggiuntiva può essere inclusa nelle etichette e nessuna può essere omessa.

Note di output

  • Le unità "riempite" della barra di avanzamento saranno rappresentate da un #personaggio. Le unità "aperte" saranno rappresentate da -.
  • Ci deve essere esattamente uno spazio tra la barra di avanzamento e ciascuna etichetta.
  • Sono consentiti spazi iniziali o finali e / o una nuova riga finale finale.

vincente

Questo è . Vince il codice più breve in byte. Si applicano le regole standard. Scappatoie standard vietate.

Esempi

Input                      Output
-----------------------    -------------------------------------
2016-12-12T12:17           12:00 ######-------------- 13:00
2016-12-12                 12-01 #######------------- 01-01
0000-01-01T00:00:00.000    00.000 -------------------- 01.000
0000-01-01T00:00           00:00 -------------------- 01:00
1899-12-31T23              31T00 ###################- 01T00
1899-12-31                 12-01 ###################- 01-01
1899-12                    1899-01 ##################-- 1900-01
1982-05-15T17:15           17:00 #####--------------- 18:00
1982-05-15T17              15T00 ##############------ 16T00
1982-05                    1982-01 #######------------- 1983-01
9999-12-31T23:59:59.999    59.000 #################### 00.000
9999-12                    9999-01 ##################-- 10000-01
2000-01-06                 01-01 ###----------------- 02-01
2000-02-06                 02-01 ###----------------- 03-01
2001-02-06                 02-01 ####---------------- 03-01
1742-09-10                 09-01 ######-------------- 10-01

4
Dobbiamo preoccuparci dei secondi saltati?
Riley,

@Riley Buona domanda. No.
Jordan

2
Suppongo che Daylight Savings sia ignorato, dal momento che non esiste un modulo standardizzato?
CAD97,

3
@ CAD97 Buona domanda. Hai ragione. L'ora legale complica davvero le cose per i viaggiatori nel tempo, quindi la ignoriamo.
Giordania,

L'esempio "1899-12-31T23" non è valido in base all'elenco dei formati di input fornito, lo stesso per "1982-05-15T17". Verifica i dati del test.
Zeppelin,

Risposte:


4

JavaScript, 282 byte

(x,v=x.split(/\D/g),l=v.length-2,[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),t=(v[l+1]-b)/d*20+.5|0,n=v[l],o=((n|0)+1)%a,r=l?('0'+o).slice(-2):o)=>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

Supera tutti i test

(
x,
v=x.split(/\D/g),
l=v.length-2,
[a,b,c,d]=("10e5,01,-,12,01,-,"+new Date(v[0],v[1],0).getDate()+",00,T,24,00,:,60,00,:,60,000,.,1000").split`,`.slice(l*3,l*3+4),
t=(v[l+1]-b)/d*20+.5|0,
n=v[l],
o=((n|0)+1)%a,
r=l?('0'+o).slice(-2):o
) =>n+c+b+' '+'#'.repeat(t)+'-'.repeat(20-t)+' '+r+c+b

La funzione di test non stampa nulla per il passaggio, valori per errore.

function test(value,expected){
    if (f(value)!=expected)
    {
        console.log(value);
        console.log(f(value));
        console.log(expected);
     }
}

I casi di test:

test('2016-12-12T12:17','12:00 ######-------------- 13:00')                 ;
test('2016-12-12','12-01 #######------------- 01-01')                       ;
test('0000-01-01T00:00:00.000','00.000 -------------------- 01.000')        ;
test('0000-01-01T00:00','00:00 -------------------- 01:00')                 ;
test('1899-12-31T23','31T00 ###################- 01T00')                    ;
test('1899-12-31','12-01 ###################- 01-01')                       ;
test('1899-12','1899-01 ##################-- 1900-01')                      ;
test('1982-05-15T17:15','17:00 #####--------------- 18:00')                 ;
test('1982-05-15T17','15T00 ##############------ 16T00')                    ;
test('1982-05','1982-01 #######------------- 1983-01')                      ;
test('9999-12-31T23:59:59.999','59.000 #################### 00.000')        ;
test('9999-12','9999-01 ##################-- 10000-01')                     ;
test('2000-01-06','01-01 ###----------------- 02-01')                       ;
test('2000-02-06','02-01 ###----------------- 03-01')                       ;
test('2001-02-06','02-01 ####---------------- 03-01')                       ;
test('1742-09-10','09-01 ######-------------- 10-01')                       ;

2
Ho dovuto imparare una nuova lingua per completare questa versione ... è molto conciso!
Rexroni,

3

Pyth, 213 byte

Il mio primo codice in Pyth! Ecco:

+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Il mio codice Pyth è strettamente basato sulla mia precedente risposta Python. Ecco la versione ungolfed con commenti:

"K is the input, as a list of numbers"
Kr:w"[-T:.]"d7
"Y=year"
=YhK
"k=month"
=k@K1
"H = a list of denominators"
=H[0 ^9T 12 ?q2k+28+q0%Y4-q0%Y400q0%Y100 +30%+k/k8 2 24 60 60 999)
"J is the second-to-last number of the input"
J@K_2
"b is the +1 starting point for months and days"
=b<lK4
"G is the number of hashtags in the statusbar"
=Gs+*20c-eKb@HlK.5
"N is the formatted string"
=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lK3 *2lK
+%hNJ+@N1+%eNb+d+*\#G+*\--20G+d+%hN%+J1@H-lK1+@N1%eNb

Il test di più valori è facilmente realizzabile eseguendo il ciclo del codice e aggiungendo una nuova riga alla fine:

Wp+%h=N:[d"%.4d"\-=Z"%.2d"\-Z\TZ\:Z\:Z\."%.3d")-*2lKr:w"[-T:.]"d7 3*2lKJ@K_2+@N1+%eN=b<lK4+d+*\#=Gs+*20c-eKb@=H[0^9T12?q2=k@K1+28+q0%=YhK4-q0%Y400q0%Y100+30%+k/k8 2 24 60 60 999)lK.5+*\--20G+d+%hN%+J1@H-lK1+@N1+%eNb"\n"

Poi mi sono imbattuto cat testinput | pyth code.pyth > outpute diff output testoutput O provare on-line .


2

Python 2, 371 byte

Questa sfida è stata sorprendentemente difficile! Sembrava che avessi poco meno di 300 finché non avessi elaborato la formattazione della stringa di output.

Il tipo di parte interessante è che la mia risposta non utilizza alcun pacchetto data:

import re
s=raw_input()
S=[int(i)for i in re.sub('[-T:.]',' ',s).split()]
l=len(S)
y,m=S[:2]
d=[0,20<<9,12,28+(y%4==0!=y%100)+(y%400==0)if m==2else 30+(m+m/8)%2,24,60,60,999]
a,n=S[-2:]
b=1-(1if l>3else 0)
h=int(20.*(n-b)/d[l]+.5)
x,y,z='- %.4d - %.2d - %.2d T %.2d : %.2d : %.2d . %.3d'.split()[l*2-3:l*2]
print x%a+y+z%b+' '+'#'*h+'-'*(20-h)+' '+x%((a+1)%d[l-1])+y+z%b
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.