1
\$\begingroup\$

Convert a binary number (of any size) into a hexadecimal number.

Input
A POSITIVE binary number with just the 0s and 1s. A valid input will always match the following regex: [0-1]+. If the input is not a valid binary number, that is, anything not matching this regex, the output should be 0 or the program should exit, or error. The output does not need the leading 0x nor does it need to be capitalized.

Output
The binary number converted to hexadecimal.

Winning
Original Code-Golf Rules, Lowest amount of bytes.

Examples

IN: [101]
OUT: [0x5] OR [5]

IN: [10000000010100100000]
OUT: [0x80520] OR [80520]

IN: [1010101]
OUT: [0x55] OR [55]

IN: [1111111111111111]
OUT: [0xFFFF] OR [FFFF] OR [0xffff] OR [ffff]

IN: [1012101]
OUT: [0]

IN: [a]
OUT: [0]

IN: [-1010101]
OUT: [0]

IN: [abcdef]
OUT: [0]

IN: [2]
OUT: [0]
\$\endgroup\$
12
  • 12
    \$\begingroup\$ Boo-urns to input validation! \$\endgroup\$
    – Shaggy
    Aug 27, 2017 at 20:19
  • 2
    \$\begingroup\$ Can we exit if the input isn't valid binary? \$\endgroup\$ Aug 27, 2017 at 20:20
  • 6
    \$\begingroup\$ @DirtyDev Popularity contest would NOT better. \$\endgroup\$ Aug 27, 2017 at 21:29
  • 11
    \$\begingroup\$ You could shave one byte off your regex: [01]+ \$\endgroup\$
    – martin
    Aug 28, 2017 at 2:10
  • 7
    \$\begingroup\$ 5 hours was far too quick to an accept a solution, especially one that does not meet the specs on invalid input. \$\endgroup\$
    – Shaggy
    Aug 28, 2017 at 9:32

28 Answers 28

3
\$\begingroup\$

MY, 8 6 5 bytes

⍞PrH↵

Try it online!

How?

  • line of raw input
  • P basify
  • r convert from binary
  • H convert to hex
  • output

Errors if input isn't correct.

\$\endgroup\$
1
\$\begingroup\$

Java, 126 119 117 110 104 Bytes

Thanks to Jakob and Zacharý

class A{public static void main(String[]s){System.out.print(Long.toHexString(Long.parseLong(s[0],2)));}}

Expanded:

class A
{
    public static void main(String[] s)
    {
        System.out.print(Long.toHexString(Long.parseLong(s[0], 2)));
    }
}
\$\endgroup\$
5
  • 1
    \$\begingroup\$ You can shorten with a function like this: codegolf.stackexchange.com/a/140570/46313 \$\endgroup\$
    – geokavel
    Aug 27, 2017 at 20:18
  • \$\begingroup\$ Or, if you want to stick with Java 7, you can submit a method definition, e.g. int f(String s){ ... }. Also, you can save bytes by using Long.toHexString and Long.parseLong. \$\endgroup\$
    – Jakob
    Aug 27, 2017 at 20:32
  • \$\begingroup\$ Also, remove the space after String[]. \$\endgroup\$
    – Adalynn
    Aug 27, 2017 at 20:32
  • \$\begingroup\$ @Downvoter: Why? \$\endgroup\$
    – Shaggy
    Aug 27, 2017 at 21:30
  • \$\begingroup\$ As @geokavel mentioned, you can use a Java 8 lambda to shorten your code, since you didn't specify in your challenge you should have a full program, and the default here on PPCG is "program or function/lambda": s->Long.toHexString(Long.parseLong(s,2)). But, if you want to stick with a full program, you can also shorten it with Java 8 by replacing class A{public static void main(String[]a){ with interface A{static void main(String[]a){. \$\endgroup\$ Sep 1, 2017 at 13:26
1
\$\begingroup\$

PHP, 25+1 bytes

<?=dechex(bindec($argn));

Run as pipe with -F.

or 27+1 bytes: (-R)

printf("%x",bindec($argn));

or 28+1 bytes: (-F)

<?=base_convert($argn,2,16);

or 30+1 bytes: (-R)

eval("printf('%x',0b$argn);");
\$\endgroup\$
1
\$\begingroup\$

C, 168 bytes

i,l,k,n;f(char*s){char*o=malloc(l=strlen(s));for(i=n=0;i<l;n+=k<<i++)if((k=s[l-i-1]-48)&&k-1)return 0;for(i=o[--l]=0;n;n/=16)k=n%16,o[l-++i]=k>9?k+55:k+48;puts(o+l-i);}

Try it online!

Unrolled:

i,l,k,n;
f(char *s)
{
    // Allocate a string for the hexadecimal digits.
    // The number of digits in the hex number is
    // sure to be less or equal to that of binary.
    char *o = malloc(l=strlen(s));

    // Convert binary to decimal.
    // The function returns zero without printing
    // anything if there are extraneous characters.
    for (i=n=0; i<l; n+=k<<i++)
        if ((k=s[l-i-1]-48) && k-1) return 0;

    // Convert decimal to hexadecimal.
    for (i=o[--l]=0; n; n/=16)
        k = n%16, o[l-++i] = k>9 ? k+55 : k+48;

    // Print the number in hexadecimal.
    puts(o+l-i);
}
\$\endgroup\$
1
\$\begingroup\$

Retina, 72 70 bytes

A`[^01]
T`d`l`.(?!(....)*$)
T`d`23`b\d
T`d`4-7`b.\d
T`d`89L`b..\d
a|b

Try it online! Output is blank on error. Edit: Saved 2 bytes thanks to @PunPun1000. Explanation:

A`[^01]

Delete non-binary input.

T`d`l`.(?!(....)*$)

Convert all digits not in the correct position to as and bs instead.

T`d`23`b\d

Add 2 to digits that follow a b.

T`d`4-7`b.\d

Add 4 to digits two after a b.

T`d`89L`b..\d

Add 8 to digits three after a b.

a|b

The as and bs have done their job and can be deleted.

\$\endgroup\$
2
  • \$\begingroup\$ 89A-F can be replaced with 89L assuming I'm reading your explanation correctly \$\endgroup\$
    – PunPun1000
    Aug 28, 2017 at 13:55
  • \$\begingroup\$ @PunPun1000 Thanks for reminding me; I knew there was something I'd overlooked. \$\endgroup\$
    – Neil
    Aug 28, 2017 at 14:48
1
\$\begingroup\$

CJam, 17 bytes

{2bGb{_9>'70?+}%}

Function that takes an array of bits as input.

Test Version

{
2b     e# Convert from base-2 to base-10.
Gb     e# Convert from base-10 to base-16.
{      e# For each digit in the hex version...
_      e# Duplicate it.
9>     e# Check if it's greater than 9.
'70?   e# If it is, add a '7' (char) to the stack. If not, add a 0 (int).
 +     e# Add the new item to the digit. Int + char => Increment char's ASCII value by int. (e.g '7' + 10 = 'A')
}%
}

If necessary, here's a version that checks for invalid input (29 bytes):

{_2,|$2,=1W?*2bGb{_9>'70?+}%}

Test Version

It outputs 0 for an empty array and throws an exception for all other invalid input.

How validation works....

{
_2,|$  e# Get Logical OR of input array and [0,1], sorted.
2,=    e# Does that equal [0,1]?
1W?    e# If the arrays are equal add 1 to the stack, if not add -1.
*      e# Repeat the input as many times as the number just added to the stack. 
       e# If the number is 1, the input is unchanged.
       e# If it's -1 you get an error for an invalid number of repetitions.
...
\$\endgroup\$
3
  • \$\begingroup\$ Does not exit, error or yield 0 for all invalid inputs. \$\endgroup\$ Aug 27, 2017 at 23:16
  • \$\begingroup\$ @Jon I did it this way because of the comments on caird's Osabie answer. I guess it's not clear what "error" as a verb means. \$\endgroup\$
    – geokavel
    Aug 27, 2017 at 23:40
  • \$\begingroup\$ There would be no point in specifying that the program should "do something unexpected given invalid input" as there is no valid output for invalid input, so I think "should error" is pretty clear (although as I commented under the OP I think input validation should really be avoided). \$\endgroup\$ Aug 27, 2017 at 23:43
1
\$\begingroup\$

R, 34 bytes

function(x)as.hexmode(strtoi(x,2))

Returns NA for invalid input.

Try it online!

\$\endgroup\$
1
\$\begingroup\$

6502 machine code (C64), 100 bytes

00 C0 20 FD AE 20 9E AD 20 A3 B6 8D 1C C0 A0 00 84 FB 84 FC 29 03 AA D0 16 A2
04 A4 FB C0 FF D0 0E A4 FC A9 00 99 62 C0 A0 C0 A9 62 4C 1E AB A9 00 85 FE CA
30 1B 06 FE A4 FB E6 FB B1 22 C9 30 F0 F1 C9 31 F0 03 4C 99 AD A5 FE 09 01 85
FE D0 E2 A9 30 05 FE C9 3A 30 02 69 06 A4 FC 99 62 C0 E6 FC D0 B5

Online demo

Usage: sys49152,"[input]", where [input] is your binary string, e.g. sys49152,"10000000010100100000".

Important: When the program was loaded from disk (like in the online demo!), issue a new command first! This is because loading the program fiddles with some BASIC pointers and the machine thinks there's no RAM left for a string...


Explanation (commented disassembly listing):

00 C0       .WORD $C000         ; load address
20 FD AE    JSR $AEFD           ; check for comma
20 9E AD    JSR $AD9E           ; evaluate expression
20 A3 B6    JSR $B6A3           ; get string from expression
8D 1C C0    STA $C01C           ; store input string length for CPY instruction
A0 00       LDY #$00            ; initialize counters to 0:
84 FB       STY $FB             ;    read counter
84 FC       STY $FC             ;    write counter
29 03       AND #$03            ; number of bits in first incomplete nibble
AA          TAX                 ;  -> to X register
D0 16       BNE .nibble         ; branch to nibble decoding if not 0
 .mainloop:
A2 04       LDX #$04            ; from here on 4 bits per nibble
A4 FB       LDY $FB             ; load read counter to Y
C0 04       CPY #$FF            ; compare with input length (argument modified)
D0 0E       BNE .nibble         ; not yet done -> branch to nibble decoding
A4 FC       LDY $FC             ; load store counter
A9 00       LDA #$00            ; write NUL terminator 
99 62 C0    STA .outbuf,Y       ; to output string
A0 C0       LDY #$C0            ; load address of
A9 62       LDA #$62            ; output string
4C 1E AB    JMP $AB1E           ; and jump to string output routine
 .nibble:
A9 00       LDA #$00            ; initialize value of nibble to zero
85 FE       STA $FE             ; store to temporary variable
 .nibbleloop:
CA          DEX                 ; decrement number of bits
30 1B       BMI .nibbleout      ; no bits left -> prepare for output
06 FE       ASL $FE             ; shift temporary variable left
A4 FB       LDY $FB             ; load read counter to Y
E6 FB       INC $FB             ; increment read counter
B1 22       LDA ($22),Y         ; load next input character
C9 30       CMP #$30            ; compare with '0'
F0 F1       BEQ .nibbleloop     ; if equal, handle next bit
C9 31       CMP #$31            ; compare with '1'
F0 03       BEQ .nibbleadd      ; if equal, add that bit
4C 99 AD    JMP $AD99           ; neither '0' or '1' -> type mismatch error
 .nibbleadd:
A5 FE       LDA $FE             ; load temporary variable
09 01       ORA #$01            ; set lowest bit
85 FE       STA $FE             ; store temporary variable
D0 E2       BNE .nibbleloop     ; handle next bit
 .nibbleout:
A9 30       LDA #$30            ; load character '0'
05 FE       ORA $FE             ; combine with value from temporary variable
C9 3A       CMP #$3A            ; result smaller than 0x39 ('9') ?
30 02       BMI .nibblestore    ; then store that
69 06       ADC #$06            ; otherwise add offset to get in range 'a'-'f'
 .nibblestore:
A4 FC       LDY $FC             ; load write counter
99 62 C0    STA .outbuf,Y       ; write to output string
E6 FC       INC $FC             ; increment write counter
D0 B5       BNE .mainloop       ; back to main loop
 .outbuf:                       ; "BSS", output string is stored from here

Remarks:

  • Input validation is fully implemented (and takes quite a few bytes, otherwise it would be possible to directly output each decoded nibble without temporary storage)

  • I took the liberty to interpret "any length" as "any length my C64 system can read from a command line as a string", which is quite limited ... 69, or if you abbreviate sys with sY 70 "bits", because the whole command line is limited to 80 characters ... hope this is acceptable :)

Screenshot

\$\endgroup\$
1
\$\begingroup\$

05AB1E, 7 6 bytes

CbQ*Ch

Try it online!
Error case

It's my first try ever to a Code Golf, advices welcomed!
Handles error cases \o/

The idea is to make the conversion from base 2 to base 10, and back to base 2. Compare the result with the initial input, if it's not the same, then the conversion have failed.

1012101 => 0
a => empty
-1010101 => 0
abcdef => empty
2 => 0

Explanation

CbQ*Ch
C  # convert input from base 2 to base 10
 b # ...and back to 2
  Q # 1 if the full conversion back and return equals the input, else 0
   * # multiply to get 0 if error case
    C # convert corrected input from base 2 to base 10
     h # convert it to base 16 
\$\endgroup\$
1
  • 1
    \$\begingroup\$ You could use b instead of 2B \$\endgroup\$
    – Emigna
    Sep 5, 2017 at 13:52
1
\$\begingroup\$

Ruby, 27 25 bytes

->b{'%x'%Integer('0b'+b)}

Try it online!

-2 bytes thanks to histocrat.

Inputs and outputs strings.

String#to_i vows to never throw an exception, returning 0 for many invalid inputs. That would be fine, except for this property:

Extraneous characters past the end of a valid number are ignored.

Meaning that 1012101 is read up to the 2 and interpreted as 101 (or 5), which is no good. We can use the stricter Integer() instead, which throws an exception for any number that is not binary. It lets through negative numbers, so we need to invalidate those by prepending 0b to the input. 0 as input returns 0, which is within the specification.

\$\endgroup\$
2
  • \$\begingroup\$ I don't think you need the ,2 unless I'm missing some corner case, since you're already specifying base 2 with the '0b'. \$\endgroup\$
    – histocrat
    Nov 20, 2017 at 22:39
  • \$\begingroup\$ @histocrat This was long enough ago that I can't really remember but I suspect you're right. Thanks! \$\endgroup\$
    – Snack
    Nov 21, 2017 at 22:31
1
\$\begingroup\$

Tcl, 66 bytes

proc H b {expr {[regexp ^\[01\]+$ $b]?[format %x [scan $b %b]]:0}}

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ There was a bug in fifth test case. Fixed now. \$\endgroup\$
    – sergiol
    Dec 23, 2017 at 11:39
0
\$\begingroup\$

Rust, 58 57 bytes

Saved one byte using 8 bit int

|n:&str|format!("{:x}",u8::from_str_radix(n,2).unwrap());

Ungolfed

fn main() {
    let bin = "101";
    println!("{:x}", u8::from_str_radix(bin, 2).unwrap()); // 5
}

Try it online!

\$\endgroup\$
0
0
\$\begingroup\$

Python 3, 52 29 26 bytes

print(hex(int(input(),2)))
\$\endgroup\$
6
  • \$\begingroup\$ It's not very golfy \$\endgroup\$
    – Adalynn
    Aug 27, 2017 at 20:33
  • \$\begingroup\$ Unfortunately, since the OP changed the rules it now only differs by being a more verbose function definition. \$\endgroup\$
    – cole
    Aug 27, 2017 at 21:17
  • \$\begingroup\$ ...plus (like the other one) does not exit, error or yield 0 for all invalid inputs. (Also you have not updated the TIO link from the 52 byter) \$\endgroup\$ Aug 27, 2017 at 23:09
  • \$\begingroup\$ You might be able to change it to Python2 (and remove the parens after print), since it would error on invalid inputs due to various different reasons. \$\endgroup\$
    – Adalynn
    Aug 27, 2017 at 23:22
  • \$\begingroup\$ @Zacharý Sadly Python 2 doesn't seem to have a hex() builtin \$\endgroup\$
    – benzene
    Aug 27, 2017 at 23:27
0
\$\begingroup\$

Stacked, 24 bytes

[:\'1|0'-#'0=\unbin*hex]

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Dyvil, 32 Bytes

s=>Int.parseInt(s,2).toHexString

Pretty much self-explanatory. Throws a NumberFormatException for invalid inputs. Output without 0x.

\$\endgroup\$
0
\$\begingroup\$

Javascript (ES6) 50 45 39 bytes

h=
s=>isNaN(n=+('0b'+s))?0:n.toString(16)   
<input id="i" type="text" onchange="o.innerHTML=h(i.value)"><pre id="o"></pre">

with thanks to Shaggy 6 bytes less. Or for a 26 byte version that returns 'NaN' instead of '0' on error:

s=>+('0b'+s).toString(16)

'0b' was introduced as a binary number prefix in ES6.

\$\endgroup\$
2
  • \$\begingroup\$ You should be able to save some bytes by moving the assignment of n within isNaN and then removing the parentheses from the function parameter. Also, does the 0 need to be a string? \$\endgroup\$
    – Shaggy
    Aug 28, 2017 at 7:29
  • \$\begingroup\$ @Shaggy - new ways to be sneaky, thanks. And also agree that 0 converts to '0' automatically when inspecting/printing the result. \$\endgroup\$
    – traktor
    Aug 28, 2017 at 9:36
0
\$\begingroup\$

Python 2, 27 bytes

lambda s:hex(int('0b'+s,2))

Try it online!

We invalidate inputs like 0b1010 or -1010 by prefixing 0b ourselves — because 0b0b1010 and 0b-1010 are invalid base 2 literals in Python.

\$\endgroup\$
2
  • \$\begingroup\$ eval('0b'+s) for a byte \$\endgroup\$
    – Uriel
    Aug 28, 2017 at 15:48
  • \$\begingroup\$ No, it’s too strong! Inputs like "0+4*5" will yield 20. \$\endgroup\$
    – Lynn
    Aug 28, 2017 at 17:28
0
\$\begingroup\$

Perl 6, 19 bytes ( = 18 + 1 for "-p" )

perl6 -pe '$_=:2($_).base: 16'

Nothing creative. The :2(string) construct takes the string and interprets it as a number in base 2. (This works for arbitrary bases up to base 36.) The base method takes a number and gives a string representation in the given base.

Due to -p, it loads one line from stdin at a time, expecting each to contain one number. If you feed it something that's not valid binary number, you get an error and the program ends.

\$\endgroup\$
0
\$\begingroup\$

Javascript, 28 bytes

x=>eval("0b"+x).toString(16)

evals x with a 0b in front of it, turning it into a binary literal. Binary literals error out on non binary values of x. .toString(16) turns x into a hexdecimal.

\$\endgroup\$
0
\$\begingroup\$

Perl 5, 30 + 1 (-n) = 31 bytes

printf"%x",!y/01//c&&oct"0b$_"

Try it online!

\$\endgroup\$
0
\$\begingroup\$

REXX, 15 bytes

say b2x(arg(1))
\$\endgroup\$
0
\$\begingroup\$

Common Lisp, 48 bytes

(format t"~X"(parse-integer(read-line):radix 2))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Julia, 24 bytes

f(x)=hex(parse(Int,x,2))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

Bash, 19 bytes

printf %x $((2#$1))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

><>, 84 82 Bytes

Improved somewhat. Probably still improvable.

l&1>:}*{$}2\~-?\02.
~~&\?&:-1&*/1l+<
>:f1+%:}\
\?:,+1f-/.47r~
)a:;!?ln/?
.47o+*b5/

Old version:

1l&>:}*{$}2\
~~&\?&:-1&*/l +<
>:f1+%:}-f1\1-?/
\?      :,+/r~
n/?)a:;!?l <
5/.4co+*b

I'll work on improving it later, see if I can get rid of that big chunk of whitespace.

How it works:

(This is for the old version, new version works the same but with loops in different positions)

Implicit input, assumed to be a series of bits such as '1,1,1,0,0', with the ones place on the right, as normal.

l&1

Store the length in the registry; push 1 to the stack. The 1 will record which place we are on in the binary number.

   >:}*{$}2\
   \?&:-1&*/

Replace each bit with the value it represents. For example, 1,1,1,0 goes to 8,4,2,0.

~~&

Delete the counter and position-measurer.

           /l +<
           \1-?/

Sum the stack. Results in the number that was represented in binary.

>:f1+%:}-f1\
\?      :,+/

Convert this to hexadecimal, which unfortunately reverses it and leaves a trailing 0. For example, 28 becomes 12, 1, 0.

           /r~

Remove the trailing zero and un-reverse it.

n/?)a:;!?l <
5/.4co+*b

This is all for printing. If the value is <10, just print it normally. Otherwise, add 55 and print the ascii character of this number.

\$\endgroup\$
0
\$\begingroup\$

Lua, 43 40 bytes

print(("").format("%x",tonumber(...,2)))

I think it explains itself. Parses from base 2 to decimal then formats it to hex. If it is not binary input it will simply error (tested with Lua 5.2,5.3).

\$\endgroup\$
0
\$\begingroup\$

><>, 50 bytes

{:?v~
!v0>}l4%?
 r
4<]nv?)9:+++*2}*4}*8[
+"W"<.33o

Try It Online

Complies with the question by erroring on invalid input, but as it always ends with an error anyway, this is a bit tongue in cheek.

How It Works

{:?v~ Pops leading 0s
...

...
!v0>}l4%? Adds leading 0s until the length of the binary is divisible by 4
 r        And reverses the input
...

...                   Repeatedly take the last 4 digits of the binary
4<]nv?)9:+++*2}*4}*8[ Calculate the value of those digits and print the hexadecimal value
+"W"<.33o             If the value is above 9, print the appropriate letter
\$\endgroup\$
0
\$\begingroup\$

Kotlin 1.1, 92 bytes

Submission

fun r(i:String):String{return if(i.matches(Regex("[01]+")))i.toLong(2).toString(16)else "0"}

Beautified

fun r(i: String): String {
    return if (i.matches(Regex("[01]+"))) {    // If it is valid
        i.toLong(2)                            // Convert to Long
         .toString(16)                         // Return as hex
    } else {                                   // Otherwise
        "0"                                    // Return 0
    }
}

Explanation

  • The number is checked to be valid by the regex
  • Kotlin to and from string methods are used to convert the string

Unfortunately this does not run on TryItOnline, as it uses newer Kotlin features

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.