Converter um número em hexadecimal


23

Desafio

Aqui está um simples.

Escreva uma função ou programa quando receber um número na base 10 como entrada, ele retornará ou imprimirá o valor desse número em hexadecimal .

Exemplos

15 -> F
1000 -> 3E8
256 -> 100

Regras

  • Nenhuma função hexadecimal incorporada, seja qual for
  • As letras podem ser minúsculas ou maiúsculas
  • Você só precisa se preocupar com números inteiros não negativos, negativos ou decimais irritantes
  • Ele deve funcionar com qualquer número arbitrariamente grande até o limite do tipo padrão do idioma.
  • Nova linha não obrigatória
  • Como sempre, esse é um , e o código mais curto medido em bytes vence!

Primeiro problema, espero que vocês gostem!
Random Guy

5
Os zeros à esquerda são permitidos na saída, por exemplo, para números de 32 bits 000003E8?
nimi

Algum limite na entrada?
Loovjo

1
@nimi Sim, isso é permitido.
Random Guy

1
Curiosidade: C ++ possui um hexadecimal embutido.
Matthew Roh

Respostas:


4

APL (Dyalog APL) , 17 bytes

Deve ser executado com ⎕IO←0, que é padrão em muitos sistemas APL.

(⎕D,⎕A)[16⊥⍣¯1⊢⎕]

Experimente online!

(⎕D,⎕A)[]D igits concatenados para A lphabet, depois indexados por…

16⊥⍣¯1  o inverso de 16-Base-para-Número, ou seja, Número-para-Base-16

 aplicado a

 entrada numérica


Não são 17 caracteres e cerca de 23 bytes?
Julie Pelletier

1
@JuliePelletier Não, o Dyalog APL usa sua própria página de códigos de 256 caracteres.
Adám 18/06/2016

Oh! Bom saber.
Julie Pelletier

14

Código da máquina de Turing, 412 bytes

Como sempre, estou usando a sintaxe da tabela de regras definida aqui. Você pode testá-lo nesse site ou, alternativamente, usando esta implementação java.

0 * * l B
B * * l C
C * 0 r D
D * * r E
E * * r A
A _ * l 1
A * * r *
1 0 9 l 1
1 1 0 l 2
1 2 1 l 2
1 3 2 l 2
1 4 3 l 2
1 5 4 l 2
1 6 5 l 2
1 7 6 l 2
1 8 7 l 2
1 9 8 l 2
1 _ * r Y
Y * * * X
X * _ r X
X _ _ * halt
2 * * l 2
2 _ _ l 3
3 * 1 r 4
3 1 2 r 4
3 2 3 r 4
3 3 4 r 4
3 4 5 r 4
3 5 6 r 4
3 6 7 r 4
3 7 8 r 4
3 8 9 r 4
3 9 A r 4
3 A B r 4
3 B C r 4
3 C D r 4
3 D E r 4
3 E F r 4
3 F 0 l 3
4 * * r 4
4 _ _ r A

Faz a contagem regressiva da entrada na base 10 e conta a partir de 0 na base 16. Ao diminuir o zero, apaga o bloco de entrada e termina.


Isso é muito legal, são necessárias 10*n + 33instruções para concluir qualquer arbitrário n. Eu não entendo o código embora.
Magic Octopus Urn

@MagicOctopusUrn Cria um novo bloco de células à esquerda da entrada, contendo inicialmente um 0. Em seguida, diminui repetidamente o bloco de entrada na base 10 enquanto incrementa o bloco de saída na base 16, até tentar diminuir uma célula vazia durante o ciclo de decréscimo [que informa que o bloco de entrada agora é 0] e, nesse momento, limpa a fita (para que apenas a saída permaneça na fita) antes de parar.
SuperJedi224

@MagicOctopusUrn Também sua equação para o tempo de execução está incorreta (não sei qual é a equação geral correta, apenas que claramente não é). Experimente com uma entrada 2, por exemplo.
SuperJedi224

provavelmente não. Parecia próximo para valores altos. Não sei nada sobre isso e estava tentando ver padrões.
Magia Octopus Urna

9

Java, 92 89 bytes

String x(int v){String z="";for(;v>0;v/=16)z="0123456789ABCDEF".charAt(v%16)+z;return z;}

9

Javascript, 49 43 bytes.

h=i=>(i?h(i>>4):0)+"0123456789abcdef"[i%16]

6 bytes salvos pelo usuário81655 .

Teste aqui .

Isso tem dois zeros à esquerda, o que é permitido pelas regras.

Aqui está uma versão sem zeros à esquerda: (47 bytes).

h=i=>(i>15?h(i>>4):"")+"0123456789abcdef"[i%16]

Teste aqui .

Ambos usam exatamente a mesma abordagem que minha resposta em Python .


Use AND binário. i&15será convertido automaticamente para inteiro, eliminando decimais. Não precisa de~~
edc65

Salvei 3 bytes e um zero à esquerda:h=i=>i&&h(i>>4)+"0123456789abcdef"[i&15]
Neil

8

CJam, 22 21 bytes

ri{Gmd_A<70s=+\}h;]W%

Obrigado a @ MartinBüttner por jogar fora um byte!

Experimente online!

Como funciona

ri                      e# Read an integer from STDIN.
  {             }h      e# Do:
   Gmd                  e#   Push qotient and residue of the division by 16.
      _A<               e#   Check if the residue is less than 10.
         70s            e#   Push "70".
            =           e#   Select the character that corresponds to the Boolean.
             +          e#   Add the character to the digit.
                        e#   This way, 10 -> 'A', etc.
               \        e#   Swap the quotient on top of the stack.
                        e# While the quotient is non-zero, repeat the loop.
                  ;     e# Pop the last quotient.
                   ]W%  e# Reverse the stack.

5
Contagem de mesmos bytes:ri{Gmd_9>7*sc+\}h;]W%
Martin Ender

6

Pitão, 33 26 21 20 bytes

Essa foi engraçada.

sm@+jkUTGi_d2_c_.BQ4

Experimente online.

Explicado:

                .BQ      Convert input to a binary string, e.g. 26 -> '11010'
             _c_   4     Reverse, chop into chunks of 4, and reverse again. We reverse 
                         because chop gives a shorter last element, and we want a shorter
                         first element: ['1', '0101']
                         Reversing three times is still shorter than using .[d4 to pad the
                         binary string to a multiple of 4 with spaces.
 m                       Map across this list:
         i_d2                Take the value of the reversed string in binary,
  @                          and use it as an index into the string:
   +jkUTG                    '0123456789abcdefghijklmnopqrstuvwxyz'
                             (The alphabet appended to the range 0 to 10)
s                        Concatenate to create the final string.

Você pode adicionar uma explicação?
TanMath

Claro, em qual você está interessado?
Lucas

A resposta mais interessante! ;) Não importa ... Embora seja uma boa idéia para explicações pós para todos eles
TanMath

5

C (função), 51

A função recursiva recebe um número inteiro de entrada como parâmetro:

f(n){n>>4?f(n>>4):0;n&=15;n+=n>9?55:48;putchar(n);}

Driver de teste:

#include <stdio.h>

f(n){if(n>>4)f(n>>4);n&=15;n+=n<10?48:55;putchar(n);}

int main (int argc, char **argv) {

    f(15);puts("");
    f(1000);puts("");
    f(256);puts("");
    f(0);puts("");

    return 0;
}

5

Haskell, 59 58 43 41 39 bytes

s="0123456789ABCDEF"
(sequence(s<$s)!!)

Exemplo de uso: sequence(s<$s)!!) $ 1000-> "00000000000003E8".

Isso cria uma lista de todos os números hexadecimais com até 16 dígitos hexadecimais. Felizmente, isso acontece em ordem, para que possamos simplesmente escolher o nth.

Edit: @Mauris espremido para fora 2 bytes. Obrigado!


Dat list monad doe
Daenyth

@Daenyth: mudei de Monad para Functor
nimi

Como sobres="0123456789ABCDEF";(sequence(s<$s)!!)
Lynn

@Mauris: incrível!
N

4

dc, 37

?[16~rd0<m]dsmxk[A~r17*+48+Pz0<p]dspx

Divmods recursivamente por 16, empurrando o restante para a pilha até que não haja mais nada para dividir. Em seguida, imprima cada elemento da pilha, usando divmod por 10 para obter dígitos AF. Provavelmente mais detalhes amanhã ... (e espero que menos bytes).


4

Python, 59 58 bytes

h=lambda i:(i>15 and h(i/16)or'')+"0123456789abcdef"[i%16]

1 byte salvo pelo CarpetPython

Correr como: print h(15)

Teste aqui (Ideone.com).

Explicação:

h=lambda i:                                                 # Define h as a function that takes two arguments
           (i>15 and h(i/16)or'')                           # Evaluate h(i/16) if i > 15, else, give ''
                                 +"0123456789abcdef"[i%16]  # Append (i%16)'th hexadecimal number.

1
Bom trabalho. Você também pode salvar outro byte com h=lambda i:(i>15 and h(i/16)or'')+"0123456789abcdef"[i%16].
Logic Knight

Bom trabalho, na verdade, você pode salvar outros dois assim:h=lambda i:(i>15 and h(i/16)or'')+chr(48+i%16+i%16/10*7)
Willem

4

C (gcc) , 45 44 bytes

f(n){n&&f(n/16);n%=16;putchar(n+48+n/10*7);}

Experimente online!


No exercício, há a frase "• Nova linha não obrigatória", isso significa que o número deve terminar com '\ n'?
RosLuP

3

Bash (função), 62

Agradecemos a @manatwork por sugerir o uso de recursão.

h()(x=({0..9} {A..F})
echo `(($1>15))&&h $[$1/16]`${x[$1%16]})

Agradável. Mas o caminho recursivo ainda parece ser mais curto:h(){ x=({0..9} {A..F});echo `(($1>15))&&h $[$1/16]`${x[$1%16]}; }
manatwork

1
@manatwork Nice - obrigado! Por alguma razão, geralmente esqueço de tentar a recursão no bash, mesmo usando-a em outras respostas. Usar em ()vez de em { ;}torno do corpo da função economiza ainda mais :)
Digital Trauma

3

Perl 6 ,  53  48 bytes

{[R~] (0..9,'A'..'F').flat[($_,*div 16...^0)X%16]||0}
{[R~] (0..9,'A'..'F').flat[.polymod(16 xx*)]||0}

Isso cria uma sequência de valores divididos por Número inteiro ( div), até que o resultado 0exclua o 0da sequência

$_, * div 16 ...^ 0

Em seguida, cruza ( X) essa sequência usando o operador de módulo ( %) com16

(  ) X[%] 16

Ele usa esses valores como índices em uma lista nivelada que consiste em dois intervalos 0..9e'A'..'Z'

( 0 .. 9, 'A' .. 'Z' ).flat[  ]

Finalmente, concatena ( ~) usando o Roperador meta (reverse )

[R[~]] 

Se isso resultar em um valor False (string vazia), retorne 0

 || 0

Uso:

# (optional) give it a lexical name for ease of use
my &code = {  }

say <15 1000 256 0>.map: &code;
# (F 3E8 100 0)

say code 10¹⁰⁰;
# 1249AD2594C37CEB0B2784C4CE0BF38ACE408E211A7CAAB24308A82E8F10000000000000000000000000

2

MATL , 27 bytes

i`16H#\wt9>?7+]wt]xN$hP48+c

Isso usa a versão 5.1.0 do idioma / compilador, que é anterior a esse desafio.

Exemplo

>> matl
 > i`16H#\wt9>?7+]wt]xN$hP48+c
 >
> 1000
3E8

Explicação

i              % input number
`              % do...
  16H#\        % remainder and quotient of division by 16
  w            % move remainder to top of stack
  t9>          % does it exceed 9?
  ?            % if so
    7+         % add 7 (for letter ASCII code)
  ]            % end if
  w            % move quotient back to the top
  t            % duplicate 
]              % ...while (duplicated) quotient is not zero
x              % delete last quotient (zero)
N$h            % create vector of all remainders 
P              % flip vector
48+c           % add 48 and convert to char (will be implicitly displayed)

2

, 31 caracteres / 62 bytes

↺a=⬯;ï;ï≫4@a=⩥ḊĀⒸª⩥⁽ṁṇ⸩⨝[ï%Ḑ]+a

Try it here (Firefox only).

Ok, eu descobri mais algumas coisas que jogavam golfe.

Explicação

É essencialmente a mesma solução que a solução ES6 do @ SuperJedi224 - mas com algo diferente.

Está vendo ⩥ḊĀⒸª⩥⁽ṁṇ⸩⨝? Essa é uma maneira muito elegante de escrever "0123456789ABCDEF". ⩥Ḋcria um intervalo de 0 a 10, Ⓒª⩥⁽ṁṇ⸩cria um intervalo de 65 a 71 e o converte em uma sequência de caracteres ASCII, e Ā...⨝concatena os dois intervalos e os une em uma sequência. Esta foi provavelmente a parte mais legal da minha solução.

Versão não competitiva de bônus, 24 caracteres / 45 bytes

↺;ï;ï≫4@ᵴ=(⩥Ḋ⨝+ᶐ)[ï%Ḑ]+ᵴ

Eu decidi adicionar uma string de alfabeto, como em Pyth.


2

sed, 341 bytes

:
s/\b/_/2
s/[13579]/&;/g
y/123456789/011223344/
s/;0/5/g
s/;1/6/g
s/;2/7/g
s/;3/8/g
s/;4/9/g
s/;_;_;_;_/=/
s/;_;_;__/+/
s/;_;__;_/:/
s/;_;___/>/
s/;__;_;_/</
s/;__;__/?/
s/;___;_/(/
s/;____/*/
s/_;_;_;_/-/
s/_;_;__/^/
s/_;__;_/%/
s/_;___/$/
s/__;_;_/#/
s/__;__/@/
s/___;_/!/
s/____/)/
/[1-9_]/b
y/)!@#$%^-*(?<>:+=/0123456789ABCDEF/
s/^0*//

Não é a linguagem óbvia para esse desafio, mas tem a vantagem de oferecer suporte a números de entrada de até (dependendo da sua implementação) entre 4000 dígitos e o limite da memória (virtual) disponível do seu sistema. Eu converti o RSA-1024 em hexadecimal em cerca de 0,6 segundos, para que ele se adapte razoavelmente bem.

Ele funciona usando divisão sucessiva por dois, acumulando a cada 4 bits de transporte em um dígito hexadecimal. Usamos caracteres que não são letras para representar nossa saída, para que sempre acumulemos carry entre a entrada decimal e a saída hexadecimal e convertemos em hexadecimal convencional no final.


2

PHP, 65 66 64 + 1 62 59 bytes

function h($n){$n&&h($n>>4);echo"0123456789abcdef"[$n&15];}

função de impressão recursiva, imprime um zero inicial (insira >16antes &&para removê-lo)


programas, 64 bytes +1 para -R(executar como canal com -nR)

for(;$n=&$argn;$n>>=4)$s="0123456789abcdef"[$n&15].$s;echo$s?:0;

requer PHP 5.6 ou posterior (o 5.5 não pode indexar literais de cadeias)

ou

for(;$n=&$argn;$n>>=4)$s=(abcdef[$n%16-10]?:$n%16).$s;echo$s?:0;

requer PHP 5.6 ou 7.0 (7.1 entende índices de string negativos)


Execute como pipe -nRou experimente-os online .


1
Estou faltando um sinal de adição echo+$spara a entrada 0
Jörg Hülsermann /

+sinal corta a saída na primeira letra ... então ...?:0
Tito

1

Julia, 55 bytes

h(n)=(n>15?h(n÷16):"")"0123456789ABCDEF"[(i=n%16+1):i]

Esta é a implementação básica da função recursiva. Ele aceita um número inteiro e retorna uma string.

Se a entrada for menor que 15, divida-a no chão por 16 e recorra, caso contrário, pegue a sequência vazia. Coloque isso na frente do caractere hexadecimal selecionado adequadamente.


1

Pyre , 98 bytes

Fazer isso em um idioma sem operadores aritméticos provavelmente foi um erro.

let h=def (n)(if n.gt(15)h(n.div(16).int!)else "").concat("0123456789abcdef".list!.get(n.mod(16)))

Use assim:

do
  let h = ...
  print(h(15))
end

Ungolfed:

let h = def (n) do
    if n.gt(15) 
        let x = h(n.div(16).int!)
    else 
        let x = ""
    x.concat("0123456789abcdef".list!.get(n.mod(16)))
end

1

Ruby, 48 caracteres

(Cópia do Loovjo 's resposta Python .)

h=->n{(n>15?h[n/16]:'')+[*?0..?9,*?a..?f][n%16]}

Exemplo de execução:

2.1.5 :001 > h=->n{(n>15?h[n/16]:'')+[*?0..?9,*?a..?f][n%16]}
 => #<Proc:0x00000001404a38@(irb):1 (lambda)> 
2.1.5 :002 > h[15]
 => "f" 
2.1.5 :003 > h[1000]
 => "3e8" 
2.1.5 :004 > h[256]
 => "100" 

1

Sério, 35 bytes

,`;4ª@%)4ª@\`╬Xε D`@;7ªD+@9<7*+c+`n

Hex Dump:

2c603b34a640252934a6405c60ce58ee204460403b37a6442b40393c372a2b632b606e

Experimente Online

Explicação:

,                                    Get evaluated input
 `          `╬                       Repeat the quoted function until top of stack is 0
  ;4ª@%                              Make a copy of the number mod 16
       )                             Send it to bottom of stack
        4ª@\                         Integer divide the original copy by 16
              X                      Delete the leftover zero. At this point the stack is 
                                     the "digits" of the hex number from LSD to MSD
               ε                     Push empty string
                 D`              `n  Essentially fold the quoted function over the stack.
                   @;                Roll up the next lowest digit, make a copy
                     7ªD+            Add 48
                         @           Bring up the other copy
                          9<         1 if it's at least 10, else 0
                            7*       Multiply with 7. 
                              +      Add. This will shift 58->65 and so on.
                               c     Convert to character.
                                +    Prepend to current string.

Observe que ;7ªD+@9<7*+cé equivalente a 4ª▀E, o que economizaria 8 bytes, mas pensei que talvez uma função que empurre os dígitos da base b como uma string possa ser considerada muito "um built-in heaxadecimal".


1

Javascript ES6, 64 58 bytes

v=>eval('for(z="";v;v>>=4)z="0123456789ABCDEF"[v%16]+z')

Economizou 6 bytes graças a ן nɟuɐɯɹɐ ן oɯ e user81655.


1
Use eval:v=>eval('for(z="";v;v=v/16|0)z="0123456789ABCDEF"[v%16]+z')
Mama Fun Roll

1
Ah, sim, tente usar atob e btoa para essa longa sequência.
Mama Fun Roll

@ (Nɟuɐɯɹɐ ן oɯ Experimentado v=>{for(z="";v>0;v=v/16|0)z=btoa``Ó]·ã»óÐ1``[v%16]+z;return z}(os dois tildes são únicos) ==> 64 caracteres, 71 bytes. Não vale a pena.
usandfriends

1
v=v/16|0é apenas uma maneira complexa de escrever v>>=4.
User81655

1

Befunge-93, 58

&:88+%"0"+:"9"`7*+\8/2/:!#|_#
,_@                       >:#

Na primeira vez em que realizamos um desafio de golfe em Befunge, aposto que há uma linha para isso, que é mais curta, já que todos esses espaços no meio da segunda linha parecem um desperdício.

Você pode passar por aqui . Explicação parcial:

&: Receber entrada.

:88+%: Pegue o restante do módulo 16.

"0"+: Adicione-o ao valor ASCII de 0.

:"9"`: Se o resultado for maior que o valor ASCII de 9 ...

7*+: Adicione 7 para convertê-lo em uma letra.

\: Salve o caractere resultante na pilha.

8/2/: Divida por 16, arredondando para baixo.

:!#|_: Saia do loop se o resultado for 0.

#: Caso contrário, volte ao passo do módulo.

>:#,_@ (empacotando): Depois de terminar, imprima a pilha na ordem LIFO.


1

> <> , 46 + 3 = 49 bytes

Isso teria sido mais curto se> <> tivesse divisão inteira, que agora temos que emular subtraindo o módulo 1. Ainda assim, acho que isso usa algumas dicas bem legais de truques!

>:?!v:f1+%:a(?v  v
\-%1:,+1f}+"0"<+7<
!?:r/ro;

Experimente online!

Explicação

Primeiro loop

>:?!v:f1+%:a(?v  v
\-%1:,+1f}+"0"<+7<

O primeiro loop executa o algoritmo clássico de conversão para hexadecimal. Faz o módulo 16 ( :f1+%) e verifica se o resultado é <10 ( :a(?). Caso contrário, precisamos adicionar 7 ( 7+) para ir das casas decimais para o alfabeto maiúsculo na tabela ASCII. Senão, podemos prosseguir adicionando o valor ASCII para 0 ( "0"+) e deslocando o caractere a ser enviado para a parte inferior da pilha, porque teremos que enviá-los na ordem inversa. O valor superior é então substituído pelo resultado da divisão inteira por 16. Isso é emulado calculando a / b - (a / b)% 1 ( f1+,:1%-). Quando o loop termina, a pilha contém os caracteres hexadecimais na ordem de saída reversa e um 0.

Segundo loop

!?:r<ro;

O segundo loop inverte a lista e verifica se o elemento superior é 0. Se for, sabemos que todos os itens diferentes de zero foram impressos e devemos terminar. Senão, produzimos o caractere e invertemos a lista novamente para preparar a próxima iteração. A :entrada do segundo loop duplicará o 0 que não tem efeito.


0

SpecBAS - 110 bytes

1 h$="0123456789ABCDEF",r$=""
2 INPUT d
4 q=INT(d/16),r=d-(q*16),r$=h$(r+1)+r$,d=q
5 IF q>15 THEN 4
6  ?h$(q+1)+r$

Isso usa um algoritmo que encontrei no WikiHow (segundo método).

As seqüências de caracteres no SpecBAS são baseadas em 1, daí a +1escolha do elemento correto.



0

Ruby, 40 bytes

Roubado de Inspirado pela resposta do manatwork, mas usando uma brecha interessante para torná-lo mais curto.

h=->n{(n>15?h[n/16]:'')+(n%16).to_s(17)}

0

REXX, 80 78 bytes

arg n
h=
do while n>0
  h=substr('0123456789ABCDEF',n//16+1,1)h
  n=n%16
  end
say h

0

C, 48 bytes

h(x){x/16&&h(x/16);x%=16;putchar(x+=48+x/10*7);}

Isso não é totalmente original, retirei 5 bytes da versão digital Trauma.


0

APL (NARS), caracteres 34, bytes 68

{⍵≤0:,'0'⋄(∇⌊⍵÷16),(1+16∣⍵)⊃⎕D,⎕A}

teste:

  g←{⍵≤0:,'0'⋄(∇⌊⍵÷16),(1+16∣⍵)⊃⎕D,⎕A}
  g 0
0
  g 100
064
  g 1000
03E8
  g 1
01
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.