Öyleyse biz hala mı?


22

Ben bir zaman yolcuyum ve zamanın geçişine takıntılıyım. Özellikle saat 12'yi geçtiğinde veya takvimimin bir sonraki sayfasına geçebildiğimde ya da herkes "Yeni Yılınız Kutlu Olsun!" Diye bağırdığı anları severim.

Lütfen bana bu son andan diğerine ne kadar uzakta olduğumu, ilerleme çubuğu şeklinde olduğumu gösteren bir program yazın. Örneğin, saat 09:12 olduğunu söylersem şunu yazması gerekir:

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

Ayın Mayıs 1982 olduğunu söylersem, şunu yazmalı:

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

Zaman yolcusu olduğumu söylemiş miydim? 0 AD'nin ilk milisaniyesinden 9999 AD'nin son milisaniyesine kadar her yere seyahat ediyorum, bu nedenle programın bu aralıktaki herhangi bir tarih ve saati ele alması gerekiyor.

Giriş

  • Giriş, aşağıdaki formatlardan birinde olacaktır:

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

    Bunlar ele alınması gereken tek format. Her bölüm tam arka sıfır (örneğin olabilir kesirli saniye anlamına gelir gösterilen basamak sayısını, olacaktır .120, hiç .12). Bu T, tarihi zamandan ayıran gerçek bir "T" harfidir. Saatler 24 saat açıktır.

  • Aylar ve günler 1 tabanlıdır (aşağıda bununla ilgili daha fazlası).

  • Geçersiz ve aralık dışı girişlerin ele alınması gerekmez.

  • Programcının takdirine bağlı olarak, girişin tek bir izleyen yeni satırı olabilir.

İlerleme çubuğu matematik

Program verilen girişteki en az ve en az ikinci derecede önemli birimlerle ilgilidir. Örneğin, girişin gün düzeyinde kesinliği varsa (örn. 2016-12-14), İlerleme çubuğu, giriş ayındaki günlerin hangi oranının kalanlara karşı geçtiğini gösterir.

İlerleme çubuğu 20 birim (karakter) ve yakın artışına yuvarlak olacak temsil oran olacaktır 1 / 20 . Örneğin, verilen 2016-12-14T12:28ilerleme çubuğunda Yuvarlak ( 2860 × 20) = "dolu" 20 birimin 9'u gösterilecektir.

1 tabanlı aylar ve günler

1 Aralık günü (örneğin) olmasına rağmen 01içinde 2016-12-01hesaplama amacı doğrultusunda, kesilmiş birimler günün 0 saat 0 dakika 0 milisaniye ima, çünkü ayın 0 günüdür. Diğer bir deyişle, 2016-12-01bir 0 / 31 Aralık boyunca yol ve 2016-12-02bir 1 / 31 , ve böyle devam eder.

Aynı şekilde, 2016-01bu nedenle hesaplamalarda o, Ocak 0. gün 0. milisaniye olan 0 / 12 olan aracı, 2016-12bir 11 / 12 .

Evet, bu ay ve günlerin ilerleme çubuğunu hiçbir zaman tam olarak dolduramayacağı anlamına gelir.

Farklı ay süreleri ve artık yıllar

Farklı ayların farklı gün sayısı vardır ve çıktılar, artık yıllar dahil, bunu yansıtmalıdır. 6 Şubat 2017'deki ilerleme çubuğu, 6 Şubat 2016'daki ilerleme çubuğundan (veya her iki yılın 6 Ocak'ından) farklı olacaktır.

Çeşitli

Çıktı

Program (veya işlev), geçen süre boyunca "doldurulmuş" ve kalan süre için "açık" olan, yatay yönlendirilmiş 20 karakterli bir ilerleme çubuğu yazdırmalıdır (veya bir dize olarak geri dönmelidir). Soldan sağa "doldurmak" zorundadır.

İlerleme çubuğunun solunda, sayılan dönemin başlangıcını gösteren bir etiketi, bir sonraki dönemin başlangıcını gösteren girişiyle aynı formatta (ancak yalnızca iki birim hassasiyet göstererek) sağında bir etiket bulunmalıdır. Örneğimiz için 2016-12-14geçerli çıktı şöyle olacaktır:

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

İşte olası dönemlerin her biri için geçerli etiket biçimleri:

  • Ay: YYYY-MM
  • Günler: MM-DD
  • Saatler: DDThh
  • dakika: hh:mm
  • saniye: mm:ss
  • milisaniyeler: ss.sss

Etiketlere ek ünite dahil edilemez ve hiçbiri ihmal edilemez.

Çıkış notları

  • İlerleme çubuğunun "doldurulmuş" birimleri bir #karakterle temsil edilir . "Açık" birimleri ile temsil edilecektir -.
  • İlerleme çubuğu ve her etiket arasında tam olarak bir boşluk bulunmalıdır.
  • Önde gelen veya izlenen boşluklara ve / veya tek bir izleyen yeni hatta izin verilir.

Kazanan

Bu . Bayt cinsinden en kısa kod kazanır. Standart kurallar geçerlidir. Standart boşluklar yasaktır.

Örnekler

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
Artık saniye için endişelenmek zorunda mıyız?
Riley

@Riley Güzel soru. Hayır.
Jordan

2
Standart bir form olmadığından Daylight Savings'in göz ardı edildiğini varsayıyorum.
CAD97,

3
@ CAD97 İyi bir soru. Haklısın. DST zaman gezginleri için işleri gerçekten karmaşık hale getiriyor, bu yüzden onu görmezden geliyoruz.
Jordan,

"1899-12-31T23" örneği, verilen "1982-05-15T17" için verilen giriş formatları listesine göre geçerli değildir. Lütfen test verilerinizi doğrulayın.
zeplin

Yanıtlar:


4

JavaScript, 282 bayt

(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

Tüm testleri geçiyor

(
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

Test işlevi başarılı olmak için hiçbir şey yazdırmaz, başarısız olmak için değerler yazdırır.

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

Test durumları:

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
Bu versiyonun başında yeni bir dil öğrenmek zorunda kaldım ... çok özlü!
rexroni

3

Pyth, 213 bayt

İlk kodumu pyth! Bakın:

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

Pyth kodum, önceki python cevabımdan yakından kaynaklanıyor. İşte yorumların ungolfed versiyonu:

"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

Birden fazla değeri test etmek, kod döngüsünü yaparak ve sonuna yeni bir satır ekleyerek kolayca gerçekleştirilebilir:

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"

Sonra koştum cat testinput | pyth code.pyth > outputve diff output testoutput Veya çevrimiçi denemek .


2

Python 2, 371 bayt

Bu zorluk şaşırtıcı derecede zordu! Çıktı dizgisini biçimlendirmeyi öğrenene kadar 300 yaşın altında olacak gibiydim.

En güzel yanı, cevabımın herhangi bir tarih paketi kullanmamasıdır:

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.