RFC 2550 - сатирична пропозиція (опублікована 1 квітня 1999 р.) Щодо космічного представлення ASCII часових позначок, які можуть підтримувати будь-яку дату (навіть ті, що були до початку Всесвіту, і ті, що минули передбачуваний кінець Всесвіту). Алгоритм обчислення часової позначки, сумісної з RFC 2550, такий (примітка: всі діапазони включають початок, але виключають кінець - від 0 до 10000 означає все, n
де 0 <= n < 10000
):
- Формат року
- Роки від 0 до 10000: 4-значний десятковий номер, обкладений лівими нулями.
- Роки від 10 000 до 100 000: 5-значний десятковий номер з префіксом символу А.
- Роки 100 000 до 10 30 : десяткове число за рік з префіксом великої літери ASCII, індекс в англійському алфавіті якого дорівнює кількості цифр у десятковому році мінус 5 (B для 6-значного року, C для 7 -дигіт років тощо).
- Року 10 30 до 10 56 : той же формат , як 10000 до 10 30 , починаючи з буквою понад з А, і додатково префіксами каретки (
^
) до рядка (так рік 10 30 представлено^A1000000000000000000000000000000
, і рік 10 31 представлена по^B10000000000000000000000000000000
). - Роки 10 56 до 10 732 : рік є префіксом двома символами та двома великими літерами ASCII. Прописні літери утворюють базове число-26, що представляє кількість цифр за рік, мінус 57.
- Роки 10 732 і далі: використовується той самий формат від 10 56 до 10 732 , розширюючи його, додаючи додаткову карету та великі літери, коли це необхідно.
- BCE років (до року 0): обчислити рядок року за абсолютною величиною року. Потім замініть усі літери на їх доповнення базою-26 (A <-> Z, B <-> Y тощо), замініть усі цифри на доповнення бази-10 (0 <-> 9, 1 <-> 8, тощо) та замініть догляд на знак оклику (
!
). Якщо рядок року становить 4 цифри або менше (тобто від -1 до -10 000), додайте косу рису вперед (/
). Якщо рядок року не префіксований косою рисою чи знаком оклику, додайте зірочку (*
).
- Місяці, дні, години, хвилини та секунди : оскільки ці значення є лише колись двома цифрами, їх просто додають праворуч від рядка року, у порядку зменшення, за необхідністю, щоб утворити ліворуч з нулями. Двозначні рядки.
- Додаткова точність : якщо потрібна додаткова точність (у формі мілісекунд, мікросекунд, наносекунд тощо), ці значення заливаються нулями до трьох цифр (оскільки кожне значення є
1/1000
попереднім значенням, і таким чином є максимум999
) і додається до кінця часової позначки, у порядку зменшення значення.
Цей формат має перевагу того, що лексичне сортування еквівалентне чисельному сортуванням відповідної часової позначки - якщо час A настає до часу B, то часова марка для A настане перед часовою позначкою для B при застосуванні лексичного сортування.
Змагання
З огляду на довільно довгий список числових значень (відповідних тимчасовим значенням у порядку зменшення, наприклад [year, month, day, hour, minute, second, millisecond]
), виведіть відповідну мітку RFC 2550.
Правила
- Рішення повинні працювати для будь-якого даного вводу. Єдиними обмеженнями повинні бути час та доступна пам'ять.
- Введення даних може здійснюватися в будь-якому розумному, зручному форматі (наприклад, список числових даних, список рядків, рядок, обмежений одним нецифровим символом тощо).
- Вхід завжди буде містити принаймні одне значення (рік). Додаткові значення завжди знаходяться в порядку зменшення значення (наприклад, введення ніколи не буде містити денного значення без місячного значення або другого значення, а потім значення місяця).
- Введення завжди буде дійсним часом (наприклад, не буде жодних часових позначок на 30 лютого).
- Вбудовані, які обчислюють часові позначки RFC 2550, заборонені.
Приклади
У цих прикладах використовується введення як один рядок, окремі значення розділені періодами ( .
).
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
Довідкова реалізація
#!/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
має бути*V3035567339896938984978971
?