Esto está inspirado en una respuesta 05AB1E de Magic Octupus Urn .
Dados dos argumentos, un entero positivo y una cadena / lista de caracteres:
- Traduzca el número a base-n, donde n es la longitud de la cadena.
- Para cada carácter, reemplace cada aparición del índice de ese carácter en el número base-n con ese carácter.
- Imprime o devuelve la nueva cadena.
Ejemplos:
Input:
2740, ["|","_"]
2740 -> 101010110100 in base 2
-> Replace 0s with "|" and 1s with "_"
Output: _|_|_|__|_||
Input:
698911, ["c","h","a","o"]
698911 -> 2222220133 in base 4
-> Replace 0s with "c", 1s with "h", 2s with "a", and 3s with "o"
Output -> "aaaaaachoo"
Input:
1928149325670647244912100789213626616560861130859431492905908574660758972167966, [" ","\n","|","_","-"]
Output:
__ __
| |_| |
___| |___
- - - -
- - - - - - -
- - - - - - - -
_______________
Input: 3446503265645381015412, [':', '\n', '.', '_', '=', ' ', ')', '(', ',']
Output:
_===_
(.,.)
( : )
( : )
Reglas:
- IO es flexible .
- Puede tomar el número en cualquier base, siempre que sea coherente entre las entradas
- Sin embargo, la lista de caracteres debe estar indexada en 0, donde 0 es el primer carácter y n-1 es el último
- Los caracteres posibles pueden ser cualquier ASCII imprimible, junto con espacios en blanco como pestañas y líneas nuevas
- La lista de caracteres dada tendrá una longitud en el rango
2-10
inclusive. Es decir, la base más pequeña es binaria y la más grande es decimal ( no hay letras molestas aquí ) - Las lagunas estándar están prohibidas
- No dude en responder incluso si su idioma no puede manejar los casos de prueba más grandes.
Como se trata de código de golf , gana el código más corto para cada idioma. ( Sé que todos los idiomas de golf tienen incorporados un byte listo para usar ;)
code-golf
ascii-art
base-conversion
Jo King
fuente
fuente
Respuestas:
05AB1E ,
76 bytesComo se inspiró en una respuesta 05AB1E, una respuesta dada en 05AB1E parece adecuada. :)
-1 byte gracias a @Enigma al eliminar el foreach y hacer esto implícitamente.
Pruébelo en línea o verifique todos los casos de prueba .
Explicación:
fuente
gв¹sèJ
para guardar un byte¹sè
mí ahora ... (sabía que cambiarlo?
a aJ
daría la misma salida en este caso)Java 8,
7250 bytes-22 bytes gracias a @ OlivierGrégoire devolviendo un en
IntStream
lugar de imprimir directamente.Pruébalo en línea .
Explicación:
fuente
a->n->n.toString(a.length).chars().map(c->a[c-48])
(50 bytes) desde "IO es flexible"String f(char[]a,int n){return n>0?f(a,n/a.length)+a[n%a.length]:"";}
(69 bytes) uno recursivo, por diversión.Python 3 , 49 bytes
No puedo comentar todavía, así que publico la respuesta de Python 2 adaptada a Python 3.5.
fuente
Japt, 2 bytes
Puede tomar la segunda entrada como una matriz o una cadena. Falla los últimos 2 casos de prueba ya que los números exceden el entero máximo de JavaScript Reemplace
s
conì
para generar una matriz de caracteres en su lugar.Intentalo
fuente
Haskell ,
4039 bytesPruébalo en línea!
Como el
Int
tipo de Haskell se limita a9223372036854775807
, esto falla para números más grandes.-1 byte gracias a Laikoni .
Sin golf
Pruébalo en línea!
fuente
cycle
lugar demod
!div n(length l)
guarda un byte.MATL , 2 bytes
Pruébalo en línea!
Las entradas son un número y una cadena.
Falla para los números que exceden
2^53
, debido a la precisión de punto flotante.Explicación
Lo que sí
YA
sé, un incorporado (conversión de base con símbolos de destino especificados).fuente
JavaScript (ES6), 48 bytes
Toma entrada en la sintaxis de curry
(c)(n)
, donde c es una lista de caracteres yn es un número entero.Seguro solo para n <2 53 .
Pruébalo en línea!
JavaScript (ES6), 99 bytes
Con soporte para enteros grandes
Toma entrada en la sintaxis de curry
(c)(a)
, donde c es una lista de caracteres y a es una lista de dígitos decimales (como enteros).Pruébalo en línea!
fuente
Código de máquina x86 de 32 bits (enteros de 32 bits): 17 bytes.
(vea también otras versiones a continuación, incluidos 16 bytes para 32 bits o 64 bits, con una convención de llamada DF = 1).
La persona que llama pasa argumentos en los registros, incluido un puntero al final de un búfer de salida (como mi respuesta C ; míralo para justificar y explicar el algoritmo). El interno de glibc
_itoa
hace esto , por lo que no solo está diseñado para el golf de código. Los registros de paso de argumentos están cerca de x86-64 System V, excepto que tenemos un argumento en EAX en lugar de EDX.Al regresar, EDI apunta al primer byte de una cadena C terminada en 0 en el búfer de salida. El registro de valor de retorno habitual es EAX / RAX, pero en lenguaje ensamblador puede usar cualquier convención de llamada que sea conveniente para una función. (
xchg eax,edi
al final agregaría 1 byte).La persona que llama puede calcular una longitud explícita si lo desea, desde
buffer_end - edi
. Pero no creo que podamos justificar la omisión del terminador a menos que la función realmente devuelva punteros de inicio + fin o puntero + longitud. Eso ahorraría 3 bytes en esta versión, pero no creo que sea justificable.idiv
. Los otros argumentos no son operandos implícitos).dec edi
, por lo que debe estar en los 4GiB bajos)nasm -felf32 ascii-compress-base.asm -l /dev/stdout | cut -b -30,$((30+10))-
(Editado a mano para reducir los comentarios, la numeración de líneas es extraña).Es sorprendente que la versión más simple, básicamente sin compensaciones de velocidad / tamaño, sea la más pequeña, pero
std
/cld
costó 2 bytes para usarstosb
en orden descendente y seguir la convención de llamadas DF = 0 común. (Y STOS disminuye después del almacenamiento, dejando el puntero apuntando un byte demasiado bajo en la salida del bucle, lo que nos cuesta bytes adicionales para evitar).Versiones
Se me ocurrieron 4 trucos de implementación significativamente diferentes (usando simple
mov
load / store (arriba), usandolea
/movsb
(ordenado pero no óptimo), usandoxchg
/xlatb
/stosb
/xchg
, y uno que ingresa al ciclo con un hack de instrucciones superpuestas. Ver código a continuación) . El último necesita un seguimiento0
en la tabla de búsqueda para copiar como terminador de cadena de salida, por lo que lo cuento como +1 byte. Dependiendo de 32/64 bits (1 byteinc
o no), y si podemos asumir que la persona que llama establece DF = 1 (stosb
descendente) o lo que sea, las diferentes versiones son (empatadas) más cortas.DF = 1 para almacenar en orden descendente lo convierte en una victoria para xchg / stosb / xchg, pero la persona que llama a menudo no querrá eso; Se siente como descargar el trabajo a la persona que llama de una manera difícil de justificar. (A diferencia de los registros personalizados de paso de argumento y valor de retorno, que generalmente no cuestan a un llamador de asm ningún trabajo adicional). Pero en el código de 64 bits,
cld
/scasb
funciona comoinc rdi
, evitando truncar el puntero de salida a 32 bits, por lo que a veces es inconveniente para preservar DF = 1 en funciones de limpieza de 64 bits. . (Los punteros a código / datos estáticos son de 32 bits en x86-64 ejecutables no PIE en Linux, y siempre en Linux x32 ABI, por lo que en algunos casos se puede usar una versión x86-64 que usa punteros de 32 bits). Esta interacción hace que sea interesante observar diferentes combinaciones de requisitos.nostring
) .stosb_edx_arg
oskew
) ; o con DF entrante = no importa, dejándolo configurado: 16 + 1Bstosb_decode_overlap
o 17Bstosb_edx_arg
stosb_decode_overlap
) , 18B (stosb_edx_arg
oskew
)x86-64 con punteros de 64 bits, otro manejo de DF: 16B (DF = 1
skew
) , 17B (nostring
con DF = 1, usando enscasb
lugar dedec
). 18B (stosb_edx_arg
preservando DF = 1 con 3 bytesinc rdi
).O si permitimos devolver un puntero a 1 byte antes de la cadena, 15B (
stosb_edx_arg
sininc
el final). Todo listo para llamar de nuevo y expandir otra cadena en el búfer con una base / tabla diferente ... Pero eso tendría más sentido si tampoco almacenamos una terminación0
, y podría poner el cuerpo de la función dentro de un bucle, así que eso es realmente un problema separadox86-64 con puntero de salida de 32 bits, convención de llamada DF = 0: no hay mejora con respecto al puntero de salida de 64 bits, pero
nostring
ahora se vincula 18B ( ).skew
). O para establecer DF = 1 y dejarlo, 17B paraskew
constd
pero nocld
. O 17 + 1B parastosb_decode_overlap
coninc edi
al final en lugar decld
/scasb
.Con una convención de llamada DF = 1: 16 bytes (IA32 o x86-64)
Requiere DF = 1 en la entrada, lo deja configurado. Apenas plausible , al menos en función de cada función. Hace lo mismo que la versión anterior, pero con xchg para obtener el resto de entrada / salida de AL antes / después de XLATB (búsqueda de tabla con R / EBX como base) y STOSB (
*output-- = al
).Con un DF = 0 normal en la convención de entrada / salida, la versión
std
/cld
/scasb
tiene 18 bytes para el código de 32 y 64 bits, y está limpia en 64 bits (funciona con un puntero de salida de 64 bits).Tenga en cuenta que los argumentos de entrada están en diferentes registros, incluido RBX para la tabla (para
xlatb
). También tenga en cuenta que este ciclo comienza almacenando AL y termina con el último carácter que aún no está almacenado (de ahímov
el final). Entonces el bucle está "sesgado" en relación con los demás, de ahí el nombre.Una versión similar no sesgada supera el EDI / RDI y luego lo arregla.
Intenté una versión alternativa de esto con
lea esi, [rbx+rdx]
/movsb
como el cuerpo del bucle interno. (RSI se restablece cada iteración, pero RDI disminuye). Pero no puede usar xor-zero / stos para el terminador, por lo que es 1 byte más grande. (Y no está limpio para 64 bits para la tabla de búsqueda sin un prefijo REX en la LEA).LUT con longitud explícita y un terminador 0: 16 + 1 bytes (32 bits)
Esta versión establece DF = 1 y lo deja así. Estoy contando el byte LUT adicional requerido como parte del recuento total de bytes.
El truco genial aquí es tener los mismos bytes decodificar de dos maneras diferentes . Caemos en el medio del bucle con resto = base y cociente = número de entrada, y copiamos el terminador 0 en su lugar.
En la primera vez a través de la función, los primeros 3 bytes del bucle se consumen como los bytes altos de un disp32 para un LEA. Esa LEA copia la base (módulo) a EDX,
idiv
produce el resto para iteraciones posteriores.El segundo byte de
idiv ebp
esFD
, que es el código de operación para lastd
instrucción que esta función necesita para funcionar. (Este fue un descubrimiento afortunado. Había estado mirando estodiv
antes, que se distingue delidiv
uso de los/r
bits en ModRM. El segundo byte dediv epb
decodifica comocmc
, que es inofensivo pero no útil. Pero conidiv ebp
eso podemos eliminarlostd
de la parte superior de la función.)Tenga en cuenta que los registros de entrada son una vez más diferencia: EBP para la base.
Este truco de decodificación superpuesta también se puede usar con
cmp eax, imm32
: solo se necesita 1 byte para avanzar de manera efectiva 4 bytes, solo banderas de clobbering. (Esto es terrible para el rendimiento en las CPU que marcan los límites de las instrucciones en la caché L1i, por cierto).Pero aquí, estamos usando 3 bytes para copiar un registro y saltar al bucle. Eso normalmente tomaría 2 + 2 (mov + jmp), y nos permitiría saltar al bucle justo antes del STOS en lugar de antes del XLATB. Pero entonces necesitaríamos una ETS por separado, y no sería muy interesante.
Pruébalo en línea! (con una
_start
persona que llama que usasys_write
en el resultado)Es mejor para la depuración ejecutarlo
strace
o reducir la salida de forma hexadecimal, para que pueda verificar que haya un\0
terminador en el lugar correcto y así sucesivamente. Pero puede ver que esto realmente funciona y producirAAAAAACHOO
para una entrada de(En realidad
xxAAAAAACHOO\0x\0\0...
, porque estamos volcando desde 2 bytes antes en el búfer a una longitud fija. Entonces podemos ver que la función escribió los bytes que se suponía que debía y no pisó ningún byte que no debería tener. El puntero de inicio que se pasó a la función fue el segundo y últimox
carácter, seguido de ceros).fuente
Jalea , 4 bytes
Pruébalo en línea!
ṃ
está literalmente incorporado para esto. Los otros tres bytes representan la indexación basada en uno de Jelly.fuente
ṃ
" Descompresión de base incorporada ; convierte x a la longitud de base (y) y luego indexa a y "? ¿Es para los casos muy excepcionales en los que la base que desea convertir y la longitud de una cadena / entero / lista son iguales? Cuando lo busco, solo puedo encontrar tres respuestas al usarlo: 1 ; 2 ; 3 . Un poco raro en todos los días, el golf de código desafía a la OMI. : S“sspspdspdspfdspfdsp”
, pero“çƥ÷£ḟ’ṃ“spdf”¤
ahorra seis bytes. Es especialmente útil con los números de base 250 de JellyPython 2 ,
4948 bytes-1 byte gracias a Jo King
Pruébalo en línea!
Versión alternativa (no terminará para números grandes),
4543 bytes-2 bytes gracias a Jo King
Pruébalo en línea!
fuente
Carbón ,
31 bytesPruébalo en línea! El enlace es a la versión detallada del código. Editar: Guardado 2 bytes gracias a @ ASCII-only. Versión anterior antes de que se agregara el incorporado, 8 bytes:
Pruébalo en línea! El enlace es a la versión detallada del código. Explicación:
fuente
θη
? Parece un poco confuso tbh. ¿Por qué no simplemente eliminarlo por completo y dejarlo⍘
?D , 112 bytes
Pruébalo en línea!
Este es un puerto de la respuesta C ++ de HatsuPointerKun
El estilo de llamada es
u(ulong(n), to!(char[])(b))
, donden
yb
son los argumentos izquierdo y derechoD cosas específicas
Lamentablemente, necesitamos importar
std.conv
para realizar conversiones de cualquier tipo por encima de una conversión de tipo muy básica.Utilizando el sistema de plantillas golfy, y dando la función de los tipos requeridos (por eso llamándolo no es sólo
u(n,b)
), podemos acortar las apariciones dechar[]
yulong
a1
byte cada uno, cuando dentro de la función f.D inicializa nuestros tipos para nosotros, por lo que
C t;
es la abreviatura deC t=cast(char[])([])
to!C
convierte el enteron%l
en una matriz de caracteres (usando puntos de código) y~
es una concatenaciónforeach(ref c;t)
es como elfor(... : ...)
bucle de C ++ , pero un poco más largo.ref
es como si&
se tratarac
como copiado por referencia (es decir, podemos modificarlot
). Por suerte, infiere D del tipo dec
sin ningún tipo de palabras clave que denota.fuente
C ++,
150144 bytes,uint64
de entrada-6 bytes gracias a Zacharý
El uso de una variable para almacenar el tamaño aumentaría el bytecount en 1
Para llamar a la función:
Primero el número, segundo es la cadena (matriz de caracteres)
Casos de prueba :
fuente
#include
, puede cambiar;;
a solo;
y'0'
puede ser simplemente48
for
ciclo:for(;n;n/=b.size())t=std::to_string(n%b.size())+t;
b.size()
no cambia en ese ciclo.Ramita, 66 bytes
Creado un
macro
que debe serimport
ed en una plantilla.Valores esperados:
Para los primeros argumentos (
n
):Para el segundo argumento (
c
):Cómo utilizar:
.twig
archivo{% import 'file.twig' as uncompress %}
uncompress.d()
Sin golf (no funcional):
Puede probar este código en: https://twigfiddle.com/54a0i9
fuente
Pyth,
987 bytesAhorré un byte gracias a hakr14 y otro gracias al Sr. Xcoder.
Pruébalo aquí
Explicación
fuente
m@Qd
con@LQ
vz
conE
.C89, rango limitado firmado
int n
,6453 byteschar **out
y modifíquelo, en lugar de tomar y devolver unchar *
Toma el número como una
int
, la tabla de búsqueda como una matriz + longitud.La salida se escribe en a
char *outbuf
. La persona que llama pasa (por referencia) un puntero al final del búfer. La función modifica ese puntero para que apunte al primer byte de la cadena al regresar.Este es un C89 válido y funciona correctamente incluso con la optimización habilitada. es decir, no depende del
-O0
comportamiento de gcc cuando se cae al final de una función no nula o tiene cualquier otra UB.Pasar un puntero al final de un búfer es normal para una función int-> string optimizada, como la interna de glibc
_itoa
. Consulte esta respuesta para obtener una explicación detallada de cómo dividir un número entero en dígitos con un bucle div / mod como lo estamos haciendo aquí, en C y en x86-64 asm. Si la base es una potencia de 2, puede cambiar / enmascarar para extraer dígitos MSD primero, pero de lo contrario, la única buena opción es el primer dígito menos significativo (con módulo).Pruébalo en línea! . Versión sin golf:
En esta versión de longitud explícita, la entrada es una
char table[]
que no necesita un byte de terminación 0, porque nunca la tratamos como una cadena. Podría ser unint table[]
para todo lo que nos importa. C no tiene contenedores que conozcan su propia longitud, por lo que puntero + longitud es la forma normal de pasar una matriz con un tamaño. Así que elegimos eso en lugar de necesitarlostrlen
.El tamaño máximo del búfer es aproximadamente
sizeof(int)*CHAR_BIT + 1
, por lo que es pequeño y constante en tiempo de compilación. (Utilizamos este espacio con base = 2 y todos los bits establecidos en 1.) por ejemplo, 33 bytes para enteros de 32 bits, incluido el0
terminador.C89, firmada
int
, tabla como una cadena C de longitud implícita, 65 bytesEsto es lo mismo, pero la entrada es una cadena de longitud implícita, por lo que tenemos que encontrar la longitud nosotros mismos.
fuente
Bash + utilidades principales , 49 bytes
Pruébalo en línea!
Comentarios / explicación
Esto toma los argumentos de la línea de comandos como entrada (el número en la base 10, luego una sola cadena con la lista de caracteres) y sale a stdout. Los caracteres especiales como el espacio, salto de línea, etc se pueden introducir en notación octal (por ejemplo,
\040
por un espacio), o\n
de una nueva línea,\t
para la lengüeta, o cualquier otra secuencia de escape queecho -e
etr
interpretar de forma idéntica.Muchos de los bytes aquí son para manejar caracteres especiales y casos de prueba más grandes. Si solo tengo que manejar caracteres no terribles y los números son pequeños (por ejemplo, el primer caso de prueba), los siguientes 24 bytes lo harán:
Esto usa la expansión de parámetros
${#2}
para obtener el número de caracteres en la cadena, crea un programa de CC para realizar la conversión base y luego envía el número convertidotr
.Sin embargo, esto no manejará nuevas líneas o espacios o pestañas, por lo que para tratar las secuencias de escape sin afectar la base, hago un recuento de caracteres
wc -c
después de interpretar los escapesecho -en
. Esto expande el programa a 38 bytes:Desafortunadamente, DC tiene una "característica" molesta en la que si está generando un gran número, lo envolverá en línea con una secuencia de barra + nueva línea, por lo que los casos de prueba más grandes tienen esta salida adicional. Para eliminarlo, canalizo la salida de CC
tr -dc 0-9
para eliminar caracteres no numéricos. Y ahí estamos.fuente
dc -e${#2}o$1p|tr 0-9 "$2"
tomar la entrada literalmente en lugar de en forma \ escape para que pueda manejar espacios, perotr
no tiene una opción para no tratar-
como un carácter de rango, por ejemplo. Si la entrada-
no tiene un extremo de la cadena, se rompe. Quizás puedas usarsed "y/0123456789/$2/"
. No, supongo que no, GNUsed
requiere que ambos argumentosy
tengan la misma longitud, y parece que se ahoga en la nueva línea.APL (Dyalog Unicode) ,
14 1312 bytesPruébalo en línea!
Función infija tácita; no puede manejar el caso de prueba más grande debido a la representación de punto flotante.
Guardado
12 bytes gracias a @ Adám!13 bytes añadidos para los encabezados:(Había olvidado que esto no se aplica ) .⎕IO←0
: I ndex O rigin = 0 y⎕FR←1287
: F loat R ePresentation = 128 bits.¿Cómo?
fuente
Adjunto , 17 bytes
Pruébalo en línea!
Explicación
fuente
Lienzo , 7 bytes.
Pruébalo aquí!
Implementación directa:
El conjunto de caracteres de entrada también puede ser una cadena siempre que no contenga una nueva línea, ya que Canvas no tiene un carácter de nueva línea y lo convierte automáticamente en un objeto 2D.
fuente
Stax ,
65 bytesEjecutar y depurarlo
Explicación:
fuente
SOGL V0.12 , 10 bytes
Pruébalo aquí!
Bastante largo, considerando que la idea está más o menos implementada en el lenguaje: aquí , ingresando
emite una cadena comprimida usando este método.
fuente
Ruby , 31 bytes
Pruébalo en línea!
fuente
Stax , 2 bytes
Ejecutar y depurarlo
:B
es una instrucción en stax que hace esto. Normalmente funcionaría en una "cadena" * en lugar de una matriz de "cadenas". Al final, esto significa que la salida es una matriz de matrices de un solo carácter. Pero la salida implícitamente se aplana de todos modos.* Stax en realidad no tiene un tipo de cadena. El texto está representado por conjuntos enteros de puntos de código.
fuente
J , 12 bytes
¿Cómo?
Pruébalo en línea!
fuente
Wolfram Language (Mathematica) , 49 bytes
Pruébalo en línea!
fuente
C (gcc) , 110 bytes
Pruébalo en línea!
Descripción:
fuente
sprintf
. Mi versión C es de 53 bytes , con el búfer de salida proporcionado por la persona que llama. Puede hacer unostrcpy
al final si desea copiar los bytes al inicio de un búfer.CJam , 11 bytes
Pruébalo en línea! Toma la entrada como el número, luego una nueva línea, luego los caracteres en el arte ASCII.
Explicación
fuente
liq
al principio, ¡y eso te ahorra 3 bytes!JavaScript, 39 bytes
Solución Python del puerto de Rod .
Pruébalo en línea
fuente
n
hasta 64 bits, ¿verdad? (Python tiene enteros de precisión arbitraria incorporados, pero los números JS sondouble
flotantes de precisión natural que se pueden convertir a enteros). No parece funcionar para los casos de prueba más grandes en la pregunta, como 1928149325670647244912100789213626616560861130859431492905908574660758972167966. Oh, pero la pregunta permite respuestas como esa. Aún así, debe tenerse en cuenta.SimpleTemplate , 86 bytes
¡Guau, este fue un gran desafío!
Esto se hizo difícil debido a la falta de acceso directo a índices específicos cuando el índice es una variable.
Un error también lo hizo más largo, requiriendo almacenar los valores dentro de una variable.
Valores esperados:
El primer argumento (
argv.0
) puede ser:El segundo argumento (
argv.1
) puede ser:¿Cómo funciona esto?
Funciona de esta manera:
C
como una matriz que contiene:C
"{@echoA."
"}"
join
función de PHP )Esto resulta, por ejemplo, en
C
contener"{@echoA.0}{@echoA.1}..."
C
Sin golf:
Puede probar este código en: https://ideone.com/NEKl2q
Resultado óptimo
Si no hubiera errores, este sería el mejor resultado, teniendo en cuenta las limitaciones (77 bytes):
fuente