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 como convert input with canonical form for given base; convert to base 10; convert to target base; convert back to specified character set with string replacement
?