Introducción
Hemos tenido algunos desafíos de conversión de base aquí en el pasado, pero no muchos diseñados para abordar números de longitud arbitrarios (es decir, números que son lo suficientemente largos como para desbordar el tipo de datos entero), y de ellos, la mayoría se sintió un poco Complicado. Tengo curiosidad por saber cómo se puede obtener un cambio de código base como este.
Desafío
Escriba un programa o función en el idioma de su elección que pueda convertir una cadena de una base en una cadena de otra base. La entrada debe ser el número a convertir (cadena), desde-base (número base 10), a base (número base 10) y el conjunto de caracteres (cadena). La salida debe ser el número convertido (cadena).
Algunos detalles y reglas adicionales son los siguientes:
- El número a ser convertido será un número entero no negativo (ya que
-
y.
puede estar en el juego de caracteres). Así también será la salida. - Los ceros iniciales (el primer carácter en el conjunto de caracteres) se deben recortar. Si el resultado es cero, debe quedar un solo dígito cero.
- El rango base mínimo admitido es de 2 a 95, que consiste en los caracteres ascii imprimibles.
- La entrada para el número a convertir, el juego de caracteres y la salida deben ser del tipo de datos de cadena. Las bases deben ser del tipo de datos entero de base 10 (o flotantes enteros).
- La longitud de la cadena del número de entrada puede ser muy grande. Es difícil cuantificar un mínimo razonable, pero se espera que pueda manejar al menos 1000 caracteres y completar la entrada de 100 caracteres en menos de 10 segundos en una máquina decente (muy generoso para este tipo de problema, pero no quiero velocidad para ser el foco).
- No puede utilizar funciones integradas de cambio de base.
- La entrada del juego de caracteres puede estar en cualquier disposición, no solo en el típico 0-9a-z ... etc.
- Suponga que solo se utilizará una entrada válida. No te preocupes por el manejo de errores.
El ganador será determinado por el código más corto que cumpla con los criterios. Se seleccionarán en al menos 7 días de base 10, o si / cuando ha habido suficientes envíos. En caso de empate, el código que se ejecute más rápido será el ganador. Si está lo suficientemente cerca en velocidad / rendimiento, la respuesta que vino antes gana.
Ejemplos
Aquí hay algunos ejemplos de entrada y salida que su código debería poder manejar:
F("1010101", 2, 10, "0123456789")
> 85
F("0001010101", 2, 10, "0123456789")
> 85
F("85", 10, 2, "0123456789")
> 1010101
F("1010101", 10, 2, "0123456789")
> 11110110100110110101
F("bababab", 2, 10, "abcdefghij")
> if
F("10", 3, 2, "0123456789")
> 11
F("<('.'<)(v'.'v)(>'.'>)(^'.'^)", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? ")
> !!~~~~~~~!!!~!~~!!!!!!!!!~~!!~!!!!!!~~!~!~!!!~!~!~!!~~!!!~!~~!!~!!~~!~!!~~!!~!~!!!~~~~!!!!!!!!!!!!~!!~!~!~~~~!~~~~!~~~~~!~~!!~~~!~!~!!!~!~~
F("~~~~~~~~~~", 31, 2, "~!@#$%^v&*()_+-=`[]{}|';:,./<>? ")
> ~
F("9876543210123456789", 10, 36, "0123456789abcdefghijklmnopqrstuvwxyz")
> 231ceddo6msr9
F("ALLYOURBASEAREBELONGTOUS", 62, 10, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
> 6173180047113843154028210391227718305282902
F("howmuchwoodcouldawoodchuckchuckifawoodchuckcouldchuckwood", 36, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? ")
> o3K9e(r_lgal0$;?w0[`<$n~</SUk(r#9W@."0&}_2?[n
F("1100111100011010101010101011001111011010101101001111101000000001010010100101111110000010001001111100000001011000000001001101110101", 2, 95, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+=[{]}\\|;:'\",<.>/? ")
> this is much shorter
You cannot use built in change-of-base functions to convert the entire input string/number at once
? Específicamente, ¿podría usar un incorporado para convertir la entrada a una base intermedia? ¿Puedo usar un incorporado para convertir a la base de destino? ¿Te gustaría algoconvert input with canonical form for given base; convert to base 10; convert to target base; convert back to specified character set with string replacement
?Respuestas:
CJam, 34 bytes
El formato de entrada es
input_N alphabet input_B output_B
cada uno en una línea separada.Ejecute todos los casos de prueba.
Explicación
Esto funciona para el mismo número de bytes:
La única diferencia es que estamos construyendo una cadena en lugar de recolectar todo en la pila y revertirlo.
fuente
Python 2 ,
11511410610594 bytesSugerencias de golf bienvenidas. Pruébalo en línea!
Editar: -9 bytes gracias a mbomb007. -2 bytes gracias a FlipTack.
Sin golf:
fuente
while z:s=d[z%t]+s;z/=t
ahorra 9 bytes.z=0
ys=''
en la declaración de función para guardar bytes.print
lugar dereturn
está permitido de forma predeterminada .En serio, 50 bytes
Hex Dump:
Estoy orgulloso de este a pesar de su longitud. ¿Por qué? Porque funcionó perfectamente en el segundo intento. Lo escribí y lo depuré en literalmente 10 minutos. Por lo general, la depuración de un programa en serio es una hora de trabajo.
Explicación:
fuente
C (función) con biblioteca GMP , 260
Esto resultó más de lo que esperaba, pero aquí está de todos modos. El
mpz_*
material realmente consume muchos bytes. Lo intenté#define M(x) mpz_##x
, pero eso me dio una ganancia neta de 10 bytes.La función
F()
es el punto de entrada. Convierte la cadena de entrada en unampz_t
por multiplicaciones sucesivas porfrom
base y la adición del índice del dígito dado en la lista de dígitos.La función
O()
es una función de salida recursiva. Cada recursión divmodsmpz_t
por elto
base. Debido a que esto produce los dígitos de salida en orden inverso, la recursión efectivamente permite que los dígitos se almacenen en la pila y se impriman en el orden correcto.Conductor de prueba:
Se agregaron nuevas líneas y sangría para facilitar la lectura.
fuente
JavaScript (ES6), 140 bytes
A diferencia del código de @ Mwr247 (que usa la aritmética de base-f para dividir s entre t cada vez, recolectando cada resto a medida que avanza) Yo uso la aritmética de base-t para multiplicar la respuesta por f cada vez, agregando cada dígito de s a medida que avanzo.
Sin golf:
fuente
Rubí,
11311210598979587 bytesDe alguna manera publiqué mi respuesta de Python (de alguna manera), así que aquí hay una respuesta de Ruby. Siete bytes más gracias a manatwork , otro byte gracias a Martin Büttner y 8 bytes más gracias a cia_rana .
Sin golf:
fuente
s=d[z%t]+s;z/=t
lugar dez,m=z.divmod t;s=d[m]+s
?APL, 10 bytes
Este es un operador APL. En APL,
⍵
y⍺
se usan para pasar valores, mientras que⍵⍵
y⍺⍺
generalmente se usan para pasar funciones. Estoy abusando de esto aquí para tener 3 argumentos.⍺⍺
es el argumento izquierdo,⍵⍵
es el argumento derecho "interno" y⍵
es el argumento derecho "externo".Básicamente:
⍺(⍺⍺{...}⍵⍵)⍵
Entonces todo lo que se necesita es
⍳
encontrar las posiciones de la cadena de entrada en la tabla "desde" y luego usar[]
para indexar en la tabla "hasta" con estas posiciones.Ejemplo:
fuente
JavaScript (ES6), 175 bytes
Supuse que ya había pasado el tiempo suficiente para enviar el que hice para crear los ejemplos. Puedo intentar jugarlo un poco mejor más tarde.
fuente
Japt, 9 bytes
Intentalo
fuente