Czy jesteśmy już wtedy?

22

Jestem podróżnikiem w czasie i mam obsesję na punkcie upływu czasu. Szczególnie podoba mi się chwila, w której wskazówki zegara mijają 12 lub kiedy mogę przejść do następnej strony mojego kalendarza lub kiedy wszyscy krzyczą „Szczęśliwego Nowego Roku”!

Proszę, napisz mi program pokazujący, jak daleko jestem od ostatniej chwili do następnej, w formie paska postępu. Na przykład, jeśli powiem, że jest godzina 09:12, powinien wydrukować to:

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

Jeśli powiem, że jest to maj 1982 r., Powinien wydrukować to:

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

Czy wspomniałem, że jestem podróżnikiem w czasie? Podróżuję do dowolnego miejsca od pierwszej milisekundy 0 AD do ostatniej milisekundy 9999 AD, więc program musi obsługiwać dowolną datę i godzinę w tym zakresie.

Wkład

  • Dane wejściowe będą miały jeden z następujących formatów:

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

    To jedyne formaty, które należy obsłużyć. Każda część będzie miała dokładnie taką liczbę wyświetlanych cyfr, co oznacza, że ​​ułamki sekund mogą mieć końcowe zera (np. .120Nigdy .12). TheTJest dosłownym litera „T” ograniczającej datę od czasu. Godziny są na zegarze 24-godzinnym.

  • Miesiące i dni są oparte na 1 (więcej na ten temat poniżej).

  • Nieprawidłowe i spoza zakresu dane wejściowe nie muszą być obsługiwane.

  • Według uznania programisty, wejście może mieć jedną końcową nową linię.

Matematyka paska postępu

Program dotyczy najmniej znaczących i drugich najmniej istotnych jednostek na danym wejściu. Na przykład, jeśli dane wejściowe mają dokładność na poziomie dnia (np. 2016-12-14), Pasek postępu wskaże, jaka część dni w miesiącu wejściowym upłynęła, a co pozostało.

Pasek postępu będzie miał 20 jednostek (znaków), a reprezentowana proporcja zostanie zaokrąglona do najbliższego przyrostu 120 . Na przykład, 2016-12-14T12:28pasek postępu pokaże Round ( 2860 × 20) = 9 z 20 jednostek „wypełnionych”.

1 miesiące i dni

Chociaż dzień 1 grudnia (na przykład) jest 01w 2016-12-01środku, dla celów obliczeń jest to 0 dzień miesiąca, ponieważ skrócone jednostki oznaczają 0 milisekundę 0 minuty 0 godziny dnia. Innymi słowy, 2016-12-01wynosi 031 drogi do grudnia i 2016-12-02wynosi 131 i tak dalej.

Podobnie 2016-01jest 0TH milisekundy z 0th dnia stycznia, zatem w obliczeniach jest 0 / 12 , czyli 2016-12jest 11 / 12 .

Tak, oznacza to, że miesiące i dni nigdy nie wypełnią całkowicie paska postępu.

Różny czas trwania miesiąca i lata przestępne

Różne miesiące mają różną liczbę dni i wynik musi to odzwierciedlać - w tym lata przestępne. Pasek postępu dla 6 lutego 2017 r. Będzie inny niż pasek postępu dla 6 lutego 2016 r. (Lub 6 stycznia obu lat).

Różne

Wydajność

Program (lub funkcja) musi wydrukować (lub zwrócić jako ciąg) zorientowany poziomo 20-znakowy pasek postępu, który jest „wypełniany” dla upływającego czasu i „otwarty” dla pozostałego czasu. Musi „wypełnić” od lewej do prawej.

Pasek postępu musi mieć etykietę po lewej stronie pokazującą początek zliczanego okresu, a drugą po prawej stronie pokazującą początek następnego okresu, w tym samym formacie co dane wejściowe (ale pokazującą tylko dwie jednostki dokładności). W naszym przykładzie 2016-12-14prawidłowe dane wyjściowe to:

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

Oto prawidłowe formaty etykiet dla każdego z możliwych okresów:

  • Miesięcy: YYYY-MM
  • Dni: MM-DD
  • Godziny: DDThh
  • Minuty: hh:mm
  • Sekundy: mm:ss
  • Milisekundy: ss.sss

Etykiety nie mogą zawierać żadnych dodatkowych jednostek i nie można ich pominąć.

Notatki wyjściowe

  • „Wypełnione” jednostki paska postępu będą reprezentowane przez #postać. Jednostki „otwarte” będą reprezentowane przez -.
  • Musi być dokładnie jedna spacja między paskiem postępu a każdą etykietą.
  • Dopuszczalne są wiodące lub końcowe spacje i / lub pojedyncza nowa linia.

Zwycięski

To jest . Najkrótszy kod w bajtach wygrywa. Obowiązują standardowe zasady. Standardowe luki zabronione.

Przykłady

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
Jordania
źródło
4
Czy musimy się martwić o sekundy przestępne?
Riley
@ Riley Dobre pytanie. Nie.
Jordan
2
Zakładam, że Daylight Savings jest ignorowany, ponieważ nie ma jednej znormalizowanej formy?
97 CAD
3
@ CAD97 Dobre pytanie. Masz rację. DST naprawdę komplikuje rzeczy dla podróżujących w czasie, więc to ignorujemy.
Jordania
Przykład „1899-12-31T23” jest nieprawidłowy zgodnie z podaną listą formatów wejściowych, to samo dla „1982-05-15T17”. Sprawdź swoje dane testowe.
zeppelin

Odpowiedzi:

4

JavaScript, 282 bajty

(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

Przechodzi wszystkie testy

(
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

Funkcja testowa nie drukuje nic dla zaliczenia, wartości dla niepowodzenia.

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

Przypadki testowe:

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')                       ;
Grax32
źródło
2
Musiałem nauczyć się nowego języka na szczycie tej wersji ... jest to bardzo zwięzłe!
rexroni
3

Pyth, 213 bajtów

Mój pierwszy kod w pyth! Ujrzeć:

+%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

Mój kod Pyth jest ściśle oparty na mojej poprzedniej odpowiedzi na python. Oto wersja bez golfa z komentarzami:

"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+*[email protected]
"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

Testowanie wielu wartości można łatwo wykonać, tworząc pętlę kodu i dodając na końcu wydruk nowego wiersza:

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"

Wtedy wpadłem cat testinput | pyth code.pyth > outputi diff output testoutput albo spróbować go online .

rexroni
źródło
2

Python 2, 371 bajtów

To wyzwanie było zaskakująco trudne! Wyglądało na to, że będę miał mniej niż 300 lat, dopóki nie opracuję formatowania ciągu wyjściowego.

Fajne jest to, że moja odpowiedź nie korzysta z żadnego pakietu dat:

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
rexroni
źródło