RFC 2550 adalah proposal satiris (diterbitkan pada 1 April 1999) untuk representasi ASCII yang efisien ruang dari cap waktu yang dapat mendukung tanggal apa pun (bahkan yang sebelum permulaan alam semesta dan yang melewati akhir alam semesta yang diprediksi). Algoritma untuk menghitung stempel waktu yang kompatibel dengan RFC 2550 adalah sebagai berikut (catatan: semua rentang mencakup awal tetapi mengecualikan akhir - 0 hingga 10.000 berarti semua n
tempat 0 <= n < 10000
):
- Format tahun
- Tahun 0 hingga 10.000: angka desimal 4 digit, diisi dengan angka nol.
- Tahun 10.000 hingga 100.000: angka desimal 5 digit, diawali dengan karakter A.
- Tahun 100.000 hingga 10 30 : angka desimal untuk tahun tersebut, diawali dengan huruf ASCII huruf besar yang indeksnya dalam alfabet bahasa Inggris sama dengan jumlah digit pada tahun desimal, minus 5 (B untuk tahun 6-digit, C untuk 7 -digit tahun, dll.).
- Tahun 10 30 hingga 10 56 : format yang sama dengan 10.000 hingga 10 30 , mulai huruf-hurufnya dengan A, dan tambahan awalan tanda sisipan (
^
) ke string (sehingga tahun 10 30 diwakili oleh^A1000000000000000000000000000000
, dan tahun 10 31 diwakili oleh oleh^B10000000000000000000000000000000
). - Tahun 10 56 hingga 10 732 : tahun diawali oleh dua tanda sisipan dan dua huruf besar ASCII. Huruf besar membentuk angka basis-26 yang mewakili jumlah digit pada tahun tersebut, minus 57.
- Tahun 10 732 dan seterusnya: format yang sama untuk 10 56 hingga 10 732 digunakan, memperpanjangnya dengan menambahkan tanda sisipan dan huruf besar tambahan bila perlu.
- Tahun SM (sebelum Tahun 0): hitung string tahun dari nilai absolut tahun tersebut. Kemudian, ganti semua huruf dengan komplemen base-26 mereka (A <-> Z, B <-> Y, dll.), Ganti semua digit dengan komplemen base-10 mereka (0 <-> 9, 1 <-> 8, dll.), dan ganti caret dengan tanda seru (
!
). Jika string tahun adalah 4 digit atau kurang (yaitu -1 hingga -10.000), tambahkan garis miring (/
). Jika string tahun tidak diawali dengan garis miring ke depan atau tanda seru, tambahkan tanda bintang (*
).
- Bulan, hari, jam, menit, dan detik : karena nilai-nilai ini hanya 2 digit paling banyak, mereka hanya ditambahkan ke kanan string tahun, dalam urutan penurunan signifikansi, berlapis kiri dengan nol jika perlu untuk membentuk String 2 digit.
- Tambahan presisi : jika presisi tambahan (dalam bentuk milidetik, mikrodetik, nanodetik, dll.) Diperlukan, nilai-nilai tersebut dibiarkan dengan nol hingga 3 digit (karena setiap nilai
1/1000
dari nilai sebelumnya, dan dengan demikian paling banyak999
) dan ditambahkan ke akhir timestamp, dalam urutan signifikansi yang menurun.
Format ini memiliki manfaat penyortiran leksikal yang setara dengan penyortiran numerik cap waktu yang sesuai - jika waktu A datang sebelum waktu B, maka timestamp untuk A akan datang sebelum timestamp untuk B ketika penyortiran leksikal diterapkan.
Tantangan
Diberikan daftar panjang nilai numerik yang sewenang-wenang (sesuai dengan nilai waktu dalam urutan signifikansi yang menurun, misalnya [year, month, day, hour, minute, second, millisecond]
), mengeluarkan stempel waktu RFC 2550 yang sesuai.
Aturan
- Solusi harus bekerja untuk setiap input yang diberikan. Satu-satunya batasan harus waktu dan memori yang tersedia.
- Input dapat diambil dalam format yang wajar dan nyaman (seperti daftar angka, daftar string, string yang dibatasi oleh karakter non-digit tunggal, dll.).
- Input akan selalu mengandung setidaknya satu nilai (tahun). Nilai tambahan selalu dalam urutan signifikansi yang menurun (mis. Input tidak akan pernah berisi nilai hari tanpa nilai bulan, atau nilai kedua diikuti oleh nilai bulan).
- Input akan selalu menjadi waktu yang valid (mis. Tidak akan ada cap waktu untuk 30 Februari).
- Builtin yang menghitung cap waktu RFC 2550 dilarang.
Contohnya
Contoh-contoh ini menggunakan input sebagai string tunggal, dengan nilai-nilai individual dipisahkan oleh titik ( .
).
1000.12.31.13.45.16.8 -> 10001231134516008
12.1.5.1 -> 0012010501
45941 -> A45941
8675309.11.16 -> C86753091116
47883552573911529811831375872990.1.1.2.3.5.8.13 -> ^B478835525739115298118313758729900101020305008013
4052107100422150625478207675901330514555829957419806023121389455865117429470888094459661251.2.3.5.7.11 -> ^^BI40521071004221506254782076759013305145558299574198060231213894558651174294708880944596612510203050711
-696443266.1.3.6.10.15.21.28 -> *V3035567330103061015021028
-5342 -> /4657
-4458159579886412234725624633605648497202 -> !Q5541840420113587765274375366394351502797
Implementasi referensi
#!/usr/bin/env python
import string
# thanks to Leaky Nun for help with this
def base26(n):
if n == 0:
return ''
digits = []
while n:
n -= 1
n, digit = divmod(n, 26)
digit += 1
if digit < 0:
n += 1
digit -= 26
digits.append(digit)
return ''.join(string.ascii_uppercase[x-1] for x in digits[::-1])
year, *vals = input().split('.')
res = ""
negative = False
if year[0] == '-':
negative = True
year = year[1:]
if len(year) < 5:
y = "{0:0>4}".format(year)
elif len(year) <= 30:
y = "{0}{1}".format(string.ascii_uppercase[len(year)-5], year)
else:
b26len = base26(len(year)-30)
y = "{0}{1}{2}".format('^'*len(b26len), b26len, year)
if negative:
y = y.translate(str.maketrans(string.ascii_uppercase+string.digits+'^', string.ascii_uppercase[::-1]+string.digits[::-1]+'!'))
if len(year) == 4:
y = '/' + y
if y[0] not in ['/', '!']:
y = '*' + y
res += y
for val in vals[:5]: #month, day, hour, minute, second
res += '{0:0>2}'.format(val)
for val in vals[5:]: #fractional seconds
res += '{0:0>3}'.format(val)
print(res)
-696443266.1.3.6.10.15.21.28
seharusnya begitu*V3035567339896938984978971
?