La RFC 2550 est une proposition satirique (publiée le 1er avril 1999) pour une représentation ASCII à faible encombrement des horodatages qui peuvent prendre en charge n'importe quelle date (même celles antérieures au début de l'univers et celles passées avant la fin prévue de l'univers). L'algorithme de calcul d'un horodatage conforme à la RFC 2550 est le suivant (remarque: toutes les plages incluent le début mais excluent la fin - 0 à 10 000 signifie tout n
où 0 <= n < 10000
):
- Format de l'année
- Années 0 à 10 000: un nombre décimal à 4 chiffres, rempli à gauche de zéros.
- Années 10 000 à 100 000: un nombre décimal à 5 chiffres, précédé du caractère A.
- Années 100 000 à 10 30 : le nombre décimal de l'année, préfixé par la lettre ASCII majuscule dont l'index de l'alphabet anglais est égal au nombre de chiffres de l'année décimale, moins 5 (B pour les années à 6 chiffres, C pour 7 - années chiffres, etc.).
- Années 10 30 à 10 56 : le même format que 10 000 à 10 30 , en commençant les lettres par A et en préfixant en plus un caret (
^
) à la chaîne (donc l'année 10 30 est représentée par^A1000000000000000000000000000000
, et l'année 10 31 est représentée par^B10000000000000000000000000000000
). - Années 10 56 à 10 732 : l'année est préfixée par deux carets et deux lettres majuscules ASCII. Les lettres majuscules forment un nombre en base 26 représentant le nombre de chiffres dans l'année, moins 57.
- À partir de 10 732 ans: le même format est utilisé pour 10 56 à 10 732 , en le prolongeant en ajoutant un caret et une lettre majuscule si nécessaire.
- Années BCE (avant l'année 0): calculez la chaîne d'année de la valeur absolue de l'année. Ensuite, remplacez toutes les lettres par leur complément en base 26 (A <-> Z, B <-> Y, etc.), remplacez tous les chiffres par leur complément en base 10 (0 <-- 9, 1 <-> 8, etc.) et remplacez les points d'insertion par des points d'exclamation (
!
). Si la chaîne de l'année est de 4 chiffres ou moins (c'est-à-dire -1 à -10 000), ajoutez une barre oblique (/
). Si la chaîne de l'année n'est pas précédée d'une barre oblique ou d'un point d'exclamation, ajoutez un astérisque (*
).
- Mois, jours, heures, minutes et secondes : comme ces valeurs ne sont que de 2 chiffres au maximum, elles sont simplement ajoutées à droite de la chaîne de l'année, par ordre décroissant de signification, complétées à gauche par des zéros si nécessaire pour former Chaînes à 2 chiffres.
- Précision supplémentaire : si une précision supplémentaire (sous forme de millisecondes, microsecondes, nanosecondes, etc.) est nécessaire, ces valeurs sont remplies à gauche avec des zéros à 3 chiffres (car chaque valeur est
1/1000
de la valeur précédente, et donc au maximum999
) et ajouté à la fin de l'horodatage, par ordre décroissant d'importance.
Ce format présente l'avantage que le tri lexical est équivalent au tri numérique de l'horodatage correspondant - si l'heure A précède l'heure B, alors l'horodatage pour A viendra avant l'horodatage pour B lorsque le tri lexical est appliqué.
Le défi
Étant donné une liste arbitrairement longue de valeurs numériques (correspondant à des valeurs temporelles dans un ordre décroissant de signification, par exemple [year, month, day, hour, minute, second, millisecond]
), émettez l'horodatage RFC 2550 correspondant.
Règles
- Les solutions doivent fonctionner pour toute entrée donnée. Les seules limitations devraient être le temps et la mémoire disponible.
- L'entrée peut être prise dans n'importe quel format raisonnable et pratique (comme une liste de chiffres, une liste de chaînes, une chaîne délimitée par un seul caractère non numérique, etc.).
- L'entrée contiendra toujours au moins une valeur (l'année). Les valeurs supplémentaires sont toujours en ordre décroissant de signification (par exemple, l'entrée ne contiendra jamais une valeur de jour sans valeur de mois, ou une deuxième valeur suivie d'une valeur de mois).
- L'entrée sera toujours une heure valide (par exemple, il n'y aura pas d'horodatage pour le 30 février).
- Les buildins qui calculent les horodatages RFC 2550 sont interdits.
Exemples
Ces exemples utilisent l'entrée comme une seule chaîne, les valeurs individuelles étant séparées par des points ( .
).
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
Implémentation de référence
#!/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
être*V3035567339896938984978971
?