Introdução
Temos alguns desafios básicos de conversão aqui no passado, mas não muitos projetados para lidar com números arbitrários de comprimento (ou seja, números longos o suficiente para transbordar o tipo de dados inteiro) e, dentre eles, mais pareceu um pouco complicado. Estou curioso para saber como é possível obter uma alteração no código base como essa.
Desafio
Escreva um programa ou função no idioma de sua escolha que possa converter uma sequência de uma base em uma sequência de outra base. A entrada deve ser o número a ser convertido (sequência), da base (número da base 10), para a base (número da base 10) e o conjunto de caracteres (sequência). A saída deve ser o número convertido (string).
Alguns detalhes e regras adicionais são os seguintes:
- O número a ser convertido será um número inteiro não negativo (uma vez
-
e.
pode ser no conjunto de caracteres). Assim também será a saída. - Os zeros à esquerda (o primeiro caractere no conjunto de caracteres) devem ser aparados. Se o resultado for zero, um único dígito zero deve permanecer.
- O intervalo base mínimo suportado é de 2 a 95, consistindo nos caracteres ascii imprimíveis.
- A entrada para o número a ser convertido, o conjunto de caracteres e a saída devem todos ser do tipo de dados da sequência. As bases devem ser do tipo de dados inteiro da base 10 (ou números inteiros flutuantes).
- O comprimento da sequência do número de entrada pode ser muito grande. É difícil quantificar um mínimo sensato, mas esperamos que ele consiga lidar com pelo menos 1000 caracteres e concluir a entrada de 100 caracteres em menos de 10 segundos em uma máquina decente (muito generosa para esse tipo de problema, mas não quero velocidade para ser o foco).
- Você não pode usar funções integradas de mudança de base.
- A entrada do conjunto de caracteres pode estar em qualquer disposição, não apenas no típico 0-9a-z ... etc.
- Suponha que apenas a entrada válida será usada. Não se preocupe com o tratamento de erros.
O vencedor será determinado pelo código mais curto que atender aos critérios. Eles serão selecionados em pelo menos 7 dias-base-10, ou se / quando houver envios suficientes. Em caso de empate, o código que correr mais rápido será o vencedor. Se perto o suficiente em velocidade / desempenho, a resposta que veio antes vence.
Exemplos
Aqui estão alguns exemplos de entrada e saída que seu código deve poder manipular:
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
? Especificamente, eu poderia usar um built-in para converter a entrada em uma base intermediária? Posso então usar um built-in para converter na base de destino? Algo comoconvert input with canonical form for given base; convert to base 10; convert to target base; convert back to specified character set with string replacement
?Respostas:
CJam, 34 bytes
O formato de entrada está
input_N alphabet input_B output_B
cada um em uma linha separada.Execute todos os casos de teste.
Explicação
Isso funciona para a mesma contagem de bytes:
A única diferença é que estamos construindo uma string em vez de coletar tudo na pilha e revertê-la.
fonte
Python 2 ,
11511410610594 bytesSugestões de golfe são bem-vindas. Experimente online!
Edit: -9 bytes graças a mbomb007. -2 bytes graças ao FlipTack.
Ungolfed:
fonte
while z:s=d[z%t]+s;z/=t
salva 9 bytes.z=0
es=''
na declaração da função para salvar bytes.print
vez dereturn
é permitido por padrão .Sério, 50 bytes
Hex Dump:
Estou orgulhoso deste, apesar de seu comprimento. Por quê? Porque funcionou perfeitamente na segunda tentativa. Eu escrevi e depurei em literalmente 10 minutos. Normalmente, a depuração de um programa Sério é uma hora de trabalho.
Explicação:
fonte
C (função) com biblioteca GMP , 260
Isso acabou mais do que eu esperava, mas aqui está assim mesmo. O
mpz_*
material realmente consome muitos bytes. Eu tentei#define M(x) mpz_##x
, mas isso deu um ganho líquido de 10 bytes.A função
F()
é o ponto de entrada. Ele converte a sequência de entrada em umampz_t
multiplicação sucessiva pelafrom
base-e adição do índice do dígito fornecido na lista de dígitos.A função
O()
é uma função de saída recursiva. Cada recursão divide ompz_t
pelato
base. Como isso gera os dígitos de saída na ordem inversa, a recursão efetivamente permite que os dígitos sejam armazenados na pilha e saídos na ordem correta.Driver de teste:
Novas linhas e recuo adicionados para facilitar a leitura.
fonte
JavaScript (ES6), 140 bytes
Ao contrário do código de @ Mwr247 (que usa aritmética base-f para dividir s por t de cada vez, coletando cada restante conforme ele avança), eu uso a aritmética base-t para multiplicar a resposta por f cada vez, adicionando cada dígito de s à medida que vou.
Ungolfed:
fonte
Ruby,
11311210598979587 bytesEu meio que publiquei duas vezes minha resposta em Python (de alguma forma), então aqui está uma resposta em Ruby. Mais sete bytes graças ao manatwork , outro byte a Martin Büttner e mais 8 bytes a cia_rana .
Ungolfed:
fonte
s=d[z%t]+s;z/=t
vez dez,m=z.divmod t;s=d[m]+s
?APL, 10 bytes
Este é um operador de APL. No APL,
⍵
e⍺
são usados para passar valores, enquanto⍵⍵
e⍺⍺
geralmente são usados para passar funções. Estou abusando disso aqui para ter 3 argumentos.⍺⍺
é o argumento da esquerda,⍵⍵
é o argumento da direita "interior" e⍵
é o argumento da direita "externo".Basicamente:
⍺(⍺⍺{...}⍵⍵)⍵
Então, tudo o que é necessário é
⍳
encontrar as posições da string de entrada na tabela "de" e, em seguida, use[]
para indexar na tabela "para" com essas posições.Exemplo:
fonte
JavaScript (ES6), 175 bytes
Achei que já faz tempo suficiente para que eu possa enviar o que fiz para criar os exemplos. Posso tentar jogar um pouco melhor depois.
fonte
Japonês, 9 bytes
Tente
fonte