RFC 2550 - это сатирическое предложение (опубликовано 1 апреля 1999 г.) для представления меток времени в формате ASCII с эффективным использованием пространства, которое может поддерживать любую дату (даже те, которые предшествуют началу вселенной и те, которые прошли после предсказанного конца вселенной). Алгоритм вычисления временной метки, соответствующей RFC 2550, следующий (примечание: все диапазоны включают начало, но исключают конец - от 0 до 10000 означают все n
где 0 <= n < 10000
):
- Формат года
- Годы от 0 до 10000: четырехзначное десятичное число, дополненное нулями.
- Годы от 10 000 до 100 000: пятизначное десятичное число с префиксом символа А.
- Годы от 100 000 до 10 30 : десятичное число для года с префиксом буквы ASCII в верхнем регистре, индекс которого в английском алфавите равен количеству цифр в десятичном году, минус 5 (B для 6-значных лет, C для 7 лет и т. д.).
- Годы с 10 30 по 10 56 : тот же формат, что и с 10 000 до 10 30 , начиная буквы с буквы A и дополнительно добавляя
^
к строке символ вставки ( ) (таким образом, год 10 30 обозначен^A1000000000000000000000000000000
, а год 10 31 представлен по^B10000000000000000000000000000000
). - Годы с 10 56 по 10 732 : году предшествуют две строчные буквы и две заглавные буквы ASCII. Заглавные буквы образуют число из 26 цифр, обозначающее количество цифр в году, минус 57.
- Года 10 732 и далее: тот же формат 10 56 10 732 используются, расширяя его путем добавления дополнительной каретки и прописными букв , когда это необходимо.
- Годы до н.э. (до года 0): вычислите строку года абсолютного значения года. Затем замените все буквы их дополнением к основанию-26 (A <-> Z, B <-> Y и т. Д.), Замените все цифры их дополнением к основанию-10 (0 <-> 9, 1 <-> 8, и т. д.) и замените каретки восклицательными знаками (
!
). Если строка года состоит из 4 цифр или менее (то есть от -1 до -10 000), добавьте косую черту (/
). Если строка года не имеет префикс перед косой чертой или восклицательный знак, добавьте звездочку (*
).
- Месяцы, дни, часы, минуты и секунды : поскольку эти значения не более 2 цифр, они просто добавляются справа от строки года, в порядке убывания значимости, с добавлением нуля слева при необходимости для формирования 2-значные строки.
- Дополнительная точность : если требуется дополнительная точность (в виде миллисекунд, микросекунд, наносекунд и т. Д.), Эти значения дополняются слева от нуля до 3 цифр (поскольку каждое значение имеет
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
?