RFC 2550 es una propuesta satírica (publicada el 1 de abril de 1999) para una representación ASCII de marcas de tiempo que ahorre espacio y que pueda admitir cualquier fecha (incluso las anteriores al comienzo del universo y las que están más allá del final previsto del universo). El algoritmo para calcular una marca de tiempo que cumple con RFC 2550 es el siguiente (nota: todos los rangos incluyen el inicio pero excluyen el final - 0 a 10,000 significa todo n
donde 0 <= n < 10000
):
- Formato de año
- Años 0 a 10,000: un número decimal de 4 dígitos, rellenado con ceros a la izquierda.
- Años 10,000 a 100,000: un número decimal de 5 dígitos, prefijado con el carácter A.
- Años 100,000 a 10 30 : el número decimal para el año, prefijado con la letra mayúscula ASCII cuyo índice en el alfabeto inglés es igual al número de dígitos en el año decimal, menos 5 (B para años de 6 dígitos, C para 7 -de años dígitos, etc.).
- Años 10 30 a 10 56 : el mismo formato que 10,000 a 10 30 , comenzando las letras de nuevo con A, y adicionalmente un prefijo caret (
^
) a la cadena (de modo que el año 10 30 está representado por^A1000000000000000000000000000000
, y el año 10 31 está representado por^B10000000000000000000000000000000
). - Años 10 56 a 10 732 : el año está precedido por dos símbolos y dos letras mayúsculas ASCII. Las letras mayúsculas forman un número de base 26 que representa el número de dígitos en el año, menos 57.
- Años 10 732 en adelante: se usa el mismo formato para 10 56 a 10 732 , extendiéndolo agregando un intercalado adicional y una letra mayúscula cuando sea necesario.
- BCE años (antes del año 0): calcule la cadena del año del valor absoluto del año. Luego, reemplace todas las letras por su complemento de base 26 (A <-> Z, B <-> Y, etc.), reemplace todos los dígitos por su complemento de base 10 (0 <-> 9, 1 <-> 8, etc.), y reemplace las marcas con signos de exclamación (
!
). Si la cadena del año tiene 4 dígitos o menos (es decir, -1 a -10,000), anteponga una barra diagonal (/
). Si la cadena del año no está precedida por una barra diagonal o un signo de exclamación, anteponga un asterisco (*
).
- Meses, días, horas, minutos y segundos : dado que estos valores tienen solo 2 dígitos como máximo, simplemente se agregan a la derecha de la cadena del año, en orden decreciente de importancia, se rellenan con ceros a la izquierda si es necesario para formar Cadenas de 2 dígitos.
- Precisión adicional : si se necesita precisión adicional (en forma de milisegundos, microsegundos, nanosegundos, etc.), esos valores se rellenan a la izquierda con ceros a 3 dígitos (porque cada valor es
1/1000
del valor anterior, y por lo tanto es como máximo999
) y se adjunta al final de la marca de tiempo, en orden decreciente de importancia.
Este formato tiene la ventaja de que la ordenación léxica es equivalente a la ordenación numérica de la marca de tiempo correspondiente: si el tiempo A llega antes que la hora B, entonces la marca de tiempo para A aparecerá antes de la marca de tiempo para B cuando se aplique la ordenación léxica.
El reto
Dada una lista arbitrariamente larga de valores numéricos (correspondientes a valores de tiempo en orden decreciente de importancia, por ejemplo [year, month, day, hour, minute, second, millisecond]
), genera la marca de tiempo RFC 2550 correspondiente.
Reglas
- Las soluciones deben funcionar para cualquier entrada dada. Las únicas limitaciones deberían ser el tiempo y la memoria disponible.
- La entrada puede tomarse en cualquier formato razonable y conveniente (como una lista de números, una lista de cadenas, una cadena delimitada por un solo carácter que no sea un dígito, etc.).
- La entrada siempre contendrá al menos un valor (el año). Los valores adicionales siempre están en orden decreciente de importancia (por ejemplo, la entrada nunca contendrá un valor de día sin un valor de mes, o un segundo valor seguido de un valor de mes).
- La entrada siempre será una hora válida (por ejemplo, no habrá ninguna marca de tiempo para el 30 de febrero).
- Las construcciones que calculan las marcas de tiempo RFC 2550 están prohibidas.
Ejemplos
Estos ejemplos usan la entrada como una sola cadena, con los valores individuales separados por puntos ( .
).
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
Implementación de referencia
#!/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
debería ser*V3035567339896938984978971
?Respuestas:
JavaScript (ES6), 325 bytes
Sorprendentemente largo.
fuente
Befunge,
418384 bytesEs difícil saber de antemano qué tan grande es probable que termine un programa Befunge, y cuando comencé a trabajar en esto pensé que en realidad podría tener alguna posibilidad de competir. Resulta que estaba equivocado.
Pruébalo en línea!
fuente
Perl 5 ,
328 322 317301 + 1 (-a
) = 302 bytesPruébalo en línea!
Sin golf
fuente
Java 8,
653640637623 bytesIngrese como
String
-array y return-type comoString
.Resultó ser bastante largo (como se esperaba), pero definitivamente se puede jugar un poco más. Me alegro de que funcione después de jugar con él durante bastante tiempo ...
Pruébalo aquí
Explicación:
for(String p:s){
: Bucle sobre las partesif(p.charAt(0)<46){p=p.substring(1);f=1;}
: Determine si es negativo y, si lo es, elimine el signo menos y establezca un indicador para reducir bytest=p.length();
: Obtener la cantidad de dígitosif(i++<1){
: Si es el primer número (el año):t<5?"000".substring(t-1)
: Si es 0-100,000 (exclusivo): agregue ceros a la izquierda si es necesariot<32?(char)(t+60)
: Si es 100,000-10 30 (exclusivo): agregue una letra inicialt<58?"^"+(char)(t+34)
: Si se trata de 10 30 -10 732 (exclusivo): Añadir un literal"^"
carta que lleva +if(t>57)for(r+="^^",u=675;u<t-57;u*=26)r+="^";
: Agregue la cantidad apropiada de literal"^"
+x="";for(String c:Long.toString(t-57,26).toUpperCase().split(""))x+=z.charAt((y+q).indexOf(c));r+=x;
: letras iniciales (conversión de base 26 a alfabeto)r+=p;
: Agregar el año en sí mismo a la cadena de resultadosif(f>0){
: Si el año fue negativo:x=t<5?"/":t<32?"*":r.replace("^","!").replaceAll("[^!]","");
: Cree una cadena temporalx
con la correcta/
,*
o una o varias!
for(char c c:r.toCharArray())x+=c>93?"":"ZYXWVUTSRQPONMLKJIHGFEDCBA9876543210".charAt((z+y).indexOf(c));
: Realice la conversión (A↔Z, B↔Y, 0↔9, 1↔8, etc.)r=x;
: Y luego establezca el resultado en esta cadena temporalx
else
: Si es el mes, días, horas, minutos, segundos, milisegundos, microsegundos, nanosegundos o menos:i>6?t<2?"00"+p:t<3?0+p:p
: Si es milisegundos o menor: agregue ceros a la izquierda si es necesario:t<2?0+p:p;
: Lo demás (mes, días, horas, minutos, segundos): agregue un cero inicial si es necesarioreturn r
: Devolver el resultadofuente
Input may be taken in any reasonable, convenient format (such as a list of numerics, a list of strings, a string delimited by a single non-digit character, etc.).
- podría tomar la entrada como una lista de números y omitir la costosa división y conversión.long
con 64 bits son los más grandes) son demasiado pequeños en Java para algunas de las entradas, por lo queString
son más cortos quejava.math.BigInteger
.String
Sin embargo, lo cambié a una matriz, así que no necesito hacer la división por puntos, lo que ahorró algunos bytes, así que gracias.Excel VBA,
500486485470 BytesFunción de ventana inmediata anónima de VBE
La función de ventana inmediata anónima de VBE que toma la entrada como año desde
[A1]
, mes desde[B1]
, días desde[C1]
, horas desde[D1]
, minutos desde[E1]
, segundos desde[F1]
y una matriz de precisión adicional opcional desde[G1:Z1]
, calcula la marca de tiempo RFC2550 y las salidas a la ventana inmediata VBE. Utiliza la función auxiliar declarada a continuación.Función auxiliar
Función auxiliar declarada que toma un número de entrada y devuelve ese número en base-26 tal que
1->A
y26->Z
Debe colocarse en un módulo público.
Uso
Debe usarse en un módulo transparente, o el módulo debe borrarse antes de la ejecución como vars
j
,o
yp
se supone que se encuentra en su estado predeterminado, no inicializado al comienzo de la ejecución del código. Paraj
, que es unaVariant\Integer
variable, este valor predeterminado es0
y parao
yp
, que sonVariant\String
variables, este valor predeterminado es la cadena vacía (""
).La entrada, una matriz de cadenas, se toma de
1:1
ActiveSheet y la salida se dirige a la ventana inmediata de VBE.Muestra de E / S
Sub
Versión de rutinaLa subrutina declarada que toma la entrada como año desde
[A1]
, mes desde[B1]
, días desde[C1]
, horas desde[D1]
, minutos desde[E1]
, segundos desde[F1]
y una matriz de precisión adicional opcional desde[G1:Z1]
, calcula la marca de tiempo RFC2550 y las salidas a la ventana inmediata de VBE.Uso
La entrada al rango
[A1:ZZ1]
puede hacerse manualmente, escribiendo en las celdas, de la izquierda a la derecha, según sea necesario o asignando desde la ventana inmediata de VBE.Es de destacar que, debido a los números de conversión automática de Excel en notación científica, cualquier número que tenga una longitud de base 10 igual o mayor a 12 dígitos debe insertarse explícitamente en la celda como texto configurando la celda para que sea una celda de texto o al anteponer el literal
'
al comienzo del valor de la celdaMuestra de E / S
Sin golfed y explicado
fuente
Jalea ,
165126bytesPruébalo en línea!
La línea 4 formatea el año con ayuda de las líneas 2 y 3. La primera y la última línea tratan con cero rellenando los elementos de la entrada a sus longitudes apropiadas y luego los concatena con el año formateado.
_µ‘l26Ċṗ@€ØAẎị@
encuentra el prefijo base 26. Toma el poder cartesiano del alfabeto (ØA
) para cada número entre 1 y ceil (log 26 (floor (log 10 (year)) - n + 1)) (donde n es 30 o 4) luego obtiene índices en esta lista con piso (log 10 (año)) - n (ị@
).ç30;€”^UZF
formatos años> = 10 30 (®L>30¤?
)ç4⁶;
formatos años <10 30 . ( Editar : guardado un byte usando en⁶;
lugar de;@⁶
)1RḊ
ḟ
da un prefijo vacío para años <10 5 (®L>4¤?
). Toma la lista de dígitos y luego filtra cada elemento en sí mismo. Simplemente usando esto para ceder[]
porque⁸
no funciona aquí.Esto solo se evalúa como[]
.⁸
y[]
no funciona aquí y no pude encontrar otros 2 bytes que devuelven una lista vacía.;®AṾ€¤
agrega el año al prefijo y luego lo aplana.L=4”/x
prefijos a/
si la duración del año es 4 en la declaración do de®S<0¤¡
.2£FiЀ¹ị€2£UF¤
toma los complementos deA .. Z
,0 .. 9
y^ /*!
si el año es negativo (®S<0¤¡
).2£
se refiere al segundo enlace,ØD,“^ *!”,ØA
que es la lista[['0' .. '9'], ['^',' ','/','*','!'], ['A' .. 'Z']]
. Con un año formateado como^C125...
este, el enlace encuentra el índice de cada carácter en la versión aplanada y2£
luego usa esos índices para construir una nueva cadena a partir de la versión aplanada2£
donde se invierte cada sublista, es decir['9' .. '0','!','*','/',' ','^','Z' .. 'A']
, cede!X874...
./
se asigna a sí mismo porque tiene el prefijo antes de que todo tome su complemento.Terminé incluyendo esto en la declaración do anterior (L=4a®S<0x@”/;
agrega un/
al comienzo de años negativos en[-9999 .. -0001]
. Supongo que esto se puede acortar.¡
) y guardé 7 bytes porque luego no tuve que probar dos años negativos.Hay muchos usosMe puse¡
en la línea 4 y creo que podrían comprimirse usando en su?
lugar, pero no estoy seguro de cómo hacer que funcionen.?
a trabajar y guardé algunos bytes.James Holderness señaló que mi primera presentación no manejó años con 30 dígitos correctos. Resultó que el error era para cualquier año que necesitara un
Z
prefijo en la base 26. Resulta que no pude usarṃ
porque cuando conviertes 26 a base 26 te da en[1,0]
lugar de26
(duh). En cambio, usé pares ordenados con reemplazo. No creo que haya un átomo para eso, pero si lo hay, puedo guardar algunos bytes. Arreglar esto terminó costándome ~ 40 bytes. Definitivamente mi programa de gelatina más largo hasta ahora. Editar : se encontró una forma más corta de hacer el producto cartesiano. Me di cuenta de que no estaba seguro de que el último funcionara para prefijos con más de dos letras de todos modos, pero la nueva forma funciona.Perdón por las muchas veces que he editado esta publicación, sigo descubriendo formas de acortarla.
fuente