12
\$\begingroup\$

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

Input
A POSITIVE hexadecimal number with a 0x in the beginning. A valid input will always match the following regex: 0x[0-9a-fA-F]+. If the input is not a valid hexadecimal number, that is, anything not matching this regex, the output should be 0.

Output
The hexadecimal converted to binary.

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

Examples

IN: 0x12
OUT: 10010

IN: 0xFF
OUT: 11111111

IN: 0XFF
OUT: 0

IN: #0ac4
OUT: 0

IN: 0x00101011
OUT: 100000001000000010001

IN: 0x525600
OUT: 10100100101011000000000

IN: 0x58f70555118ec400
OUT: 101100011110111000001010101010100010001100011101100010000000000

IN: 0x6669795966AF3000
OUT: 110011001101001011110010101100101100110101011110011000000000000

IN: 0b018474
OUT: 0

IN: 9577383
OUT: 0

IN: -483355
OUT: 0

IN: -0xf9ad92
OUT: 0

IN: 0xG
OUT: 0

IN: 0x0xa
OUT: 0
\$\endgroup\$
9
  • 7
    \$\begingroup\$ When you say "If the input isn't a valid hexadecimal number", what types of things can it be? A number in a different base? A non-numeric object? Some object made to crash the program is evaluated, possibly in a non-catchable way? Really, I would have suggested avoiding input validation at all; it feels like a chameleon challenge. \$\endgroup\$
    – xnor
    Commented Apr 12, 2017 at 3:15
  • 2
    \$\begingroup\$ Inferring rules from test cases is not OK and likely will get the challenge closed as unclear. Besides that, the examples aren't clear to me. "#0ac4" makes it seem like any extra character(s) can be included. \$\endgroup\$
    – xnor
    Commented Apr 12, 2017 at 3:21
  • 1
    \$\begingroup\$ I'm still not clear after the edit what inputs are possible. Is #0ac4 still a valid test case? \$\endgroup\$
    – xnor
    Commented Apr 12, 2017 at 3:45
  • 5
    \$\begingroup\$ Your second testcase doesn't match your regex (the X is uppercase). \$\endgroup\$
    – Dada
    Commented Apr 12, 2017 at 8:05
  • 2
    \$\begingroup\$ Do we need to take care of leading zeroes? Can we output something like 00011010 \$\endgroup\$
    – user41805
    Commented Apr 12, 2017 at 11:34

21 Answers 21

8
\$\begingroup\$

Python 2, 67 62 60 59 bytes

n=input()
try:print bin(int(n,n[1]<'x'))[2:]
except:print 0

Try it online!

Version that errors on invalid input (27 bytes):

lambda n:bin(int(n,16))[2:]

Try it online!

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

Pyth, 15 bytes

.B&qr0<z2"0x"vz

Explanation:

             vz  Evaluate the input as a literal, to get a number (casts to integer for hexadecimal input)
      <z2        Select the first two characters of (string) input
    r0           cast to lowercase (0X -> 0x)
   q     "0x"    check whether the text starts with "0x" or "0X" (negative numbers don't) 
  &              If it does, return the casted number
.B               and convert to binary string

Test Suite

With a rules clarification (that 0x must be lowercase) in the OP, you can remove r0 for 13 bytes.

.B&q<z2"0x"vz
\$\endgroup\$
3
\$\begingroup\$

Swift 5.10, 102 101 bytes

Uses Swift regex literals introduced in 5.7, after the question was asked.

let c={(s:String)in s.contains(/^0x[0-9a-fA-F]+$/) ?.init(Int(s.dropFirst(2),radix:16)!,radix:2):"0"}

Explanation/Long version

func convert(_ string: String) -> String {
    // Check input matches format
    if string.contains(/^0x[0-9a-fA-F]+$/) {
        // Prep input to be converted
        let stringWithout0xPrefix = string.dropFirst(2)
        // Conversion work
        let hexStringAsDecimal = Int(stringWithout0xPrefix, radix: 16)!
        let decimalStringAsBoolean = String(hexStringAsDecimal, radix: 2)
        return decimalStringAsBoolean
    } else {
        // Default case
        return "0"
    }
}
\$\endgroup\$
1
  • 2
    \$\begingroup\$ Welcome to Code Golf, and nice first answer! Be sure to check out our Tips for golfing in Swift page for ways you can golf your program. Also, it's fine to use languages/features more recent than the challenge, that rule was changed years ago. \$\endgroup\$
    – emanresu A
    Commented Apr 16 at 7:25
2
\$\begingroup\$

05AB1E, 11 bytes

Î2£„0xQi¹Hb

Try it online!

Explanation

Î             # initialize stack with 0 and push input
 2£           # get the first 2 chars of input
   „0xQ       # compare to "0x"
       i      # if equal
        ¹H    # convert input from base-16 to base-10
          b   # convert to binary
\$\endgroup\$
4
  • \$\begingroup\$ Doesn't work with the test case 0XFF. \$\endgroup\$
    – Okx
    Commented Apr 12, 2017 at 9:15
  • \$\begingroup\$ @Okx: Both the regex and the input section of the question states that correct input starts with 0x so I'd say that specific test-case is wrong. \$\endgroup\$
    – Emigna
    Commented Apr 12, 2017 at 9:17
  • 1
    \$\begingroup\$ Ah yeah, I didn't notice that. \$\endgroup\$
    – Okx
    Commented Apr 12, 2017 at 9:18
  • \$\begingroup\$ 9 bytes by using the new Å? or 10 bytes by still using the legacy. \$\endgroup\$ Commented Jan 17, 2019 at 18:31
2
\$\begingroup\$

JavaScript (Node.js), 92 bytes

x=>/^0000x0*([01]+)$|/i.exec(x.replace(/./g,c=>('0x1'+c-0||1+c).toString(2).slice(1)))[1]||0

Try it online!

no 253 limit

JavaScript (Node.js), 37 bytes

to compare with Shaggy's solution

x=>(/x/i.test(x[1])*x||0).toString(2)

Try it online!

253 limit, issue when x end with space

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

Batch, 402 bytes

@echo off
set/ps=
set r=0
if not %s:~0,2%==0x goto g
if %s%==0x goto g
if %s:0=%==x goto g
set t=%s%
for %%h in (0 1 2 3 4 5 6 7 8 9 a b c d e f)do call set t=%%t:%%h=%%
if not %t%==x goto g
set s=%s:~2%
for %%h in (0.0000 1.0001 2.0010 3.0011 4.0100 5.0101 6.0110 7.0111 8.1000 9.1001 a.1010 b.1011 c.1100 d.1101 e.1110 f.1111)do call set s=%%s:%%~nh=%%~xh%%
set r=%s:.=%
:g
echo %r:*1=1%

Takes input on STDIN. 8 lines are then mostly wasted on input validation, so the interesting lines are line 11, which replaces each hex digit with its binary equivalent, but due to Batch limitations, with a leading ., line 12, which deletes all the .s, and line 14, which removes leading 0s. However this fails for inputs like 0x0 so I "invalidate" those which means 0 is output instead.

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

Perl 6, 35 bytes

{(m/^0x(.+)/&&:16(~$0)//0).base(2)}
\$\endgroup\$
1
\$\begingroup\$

PHP, 66 65 63 bytes

<?=decbin(hexdec(preg_filter("#^0x([a-f\d]+$)#i","$1",$argn)));

run as pipe with -F.

Without the 0x, the worst problem would be that both hexdec and base_convert simply ignore characters that are not hex; but with it, there has to be an explicit validity check anyway.


45 bytes without the 0x:

<?=decbin(ctype_xdigit($argn)*hexdec($argn));
\$\endgroup\$
5
  • \$\begingroup\$ echo stristr($a=$argn,"0X")==$a?decbin(hexdec(ltrim($a,Xx0))):0; Is this a nice Alternative? It should working for the given testcases \$\endgroup\$ Commented Apr 12, 2017 at 17:25
  • \$\begingroup\$ @JörgHülsermann: It´s a nice alternative, and it´s working for all given test cases, but it does not check the hex value for validity (see my comment on hexdec and base_convert). \$\endgroup\$
    – Titus
    Commented Apr 14, 2017 at 9:22
  • \$\begingroup\$ I know and I think the question is a joke with the given testcases. \$\endgroup\$ Commented Apr 14, 2017 at 10:51
  • 1
    \$\begingroup\$ echo decbin(hexdec(preg_filter("#^0x([a-f\d]+$)#i","$1",$argn))); \$\endgroup\$
    – Christoph
    Commented Apr 14, 2017 at 21:29
  • \$\begingroup\$ -2 Bytes <?= istead of echo with -F option \$\endgroup\$ Commented Jun 13, 2017 at 23:34
1
\$\begingroup\$

Python 3.11 - 59

Inspired by mathjunkie's

try:x=bin(int(n:=input(),n[1]<'x'))[2:]
except:x=0
print(x)

Using the new walrus operator := to save a newline byte to store the input, but having to use an extra byte for print()'s parentheses, keeping the total byte count equal to the original.

int(n, 16) would also accept "10" as valid input and print "10000" (ie. hex 0x10, dec 16), so we need some way to validate that it starts with 0x. I couldn't find a shorter way than the original ,n[1]<'x' since int(n, False) understands the "0x" prefix and int(n, True) raises a ValueError.

The [2:] is necessary since bin() always replies with leading 0b

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

PowerShell Core, 74 bytes

param($a)if($a-cmatch'^0x[0-9a-fA-F]+$'){[Convert]::ToString($a,2)}else{0}

Try it online!

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

REXX, 45 bytes

arg '0X' n
if n>'' then say x2b(n)
else say 0
\$\endgroup\$
0
\$\begingroup\$

Retina, 149 bytes

.
;$&
T`L`l
f
71
e
70
d
61
c
60
b
51
a
50
9
41
8
40
7
31
6
30
5
21
4
20
3
11
2
10
;(\d{4})
$1
;(\d{3})
0$1
;(\d\d)
00$1
;
000
^(?!0{7}x).*
0
0{7}x0*

(note the trailing newline)

Try it online!

Here is an alternate solution at the cost of 7 bytes: Try it!

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

perl, 25

(code 24 + 1 flag -n)

printf"%8b",/^0x/i?hex:0
\$\endgroup\$
0
\$\begingroup\$

8086 machine code - 63 bytes

Works for any input up to 125 chars (the maximum command line length in DOS)

00000000  be 82 00 bf 3f 01 89 fa  ad 3d 30 78 75 24 ac 3c  |....?....=0xu$.<|
00000010  0d 74 22 2c 30 3c 09 76  08 24 df 2c 07 3c 0f 77  |.t",0<.v.$.,.<.w|
00000020  11 b1 04 c1 e0 0c d0 e4  0f 92 c0 0c 30 aa e2 f6  |............0...|
00000030  eb dc ba 3d 01 b0 24 aa  b4 09 cd 21 c3 30 24     |...=..$....!.0$|
0000003f
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 53 52 49 50 52 45 bytes

(Non-competing as it doesn't handle inputs of any size; I just got lucky with the sample inputs)

f=

h=>+/^0x[\da-f]+$/i.test(h)&&(+h).toString(2)

console.log(f`0x12`);
console.log(f`0XFF`);
console.log(f`#0ac4`);
console.log(f`0x00101011`);
console.log(f`0x525600`);
console.log(f`0x58f70555118ec400`);
console.log(f`0x6669795966AF3000`);
console.log(f`0b018474`);
console.log(f`9577383`);
console.log(f`-483355`);
console.log(f`-0xf9ad92`);

\$\endgroup\$
1
  • \$\begingroup\$ Well, it can process input of any size using BigInt: f= h=>+/^0x[\da-f]+$/i.test(h)&&(BigInt(h)).toString(2) \$\endgroup\$
    – None1
    Commented Apr 19 at 11:54
0
\$\begingroup\$

CJam, 24 bytes

q2/("0x"={seu:~Gb2bo}&;0

Try it online!

Explanation

q      e# Read the input
2/     e# Split it into 2-length segments
(      e# Pull out the first segment
"0x"=  e# Check if it equals "0x"
{      e# If it does, run this block:
 s     e#  Join the segments back together
 eu    e#  Make the string uppercase
 :~    e#  Eval each character (A-K are 10-20)
 Gb    e#  Convert from base 16 to base 10
 2b    e#  Convert to base 2
 o     e#  Output the binary number
}&     e# (end of block)
;0     e# Delete the top stack element and push 0. If the block was run, nothing is left
       e# on the stack, so the program terminates with an error before pushing 0.
\$\endgroup\$
0
\$\begingroup\$

JavaScript (ES6), 107 characters

f=
b=>/0x[\da-f]+$/i.test(b)&&b.match(/[\da-f](?!x)/gi).map(x=>((+('0x1'+x)).toString(2)).slice(-4)).join('')||0

console.log(f('0x1f'))
console.log(f('0x6669795966AF3000'))

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

Javascript, 63 bytes

f=
x=>0|/^0x[A-Fa-f0-9]+$/.test(x)&&Number.parseInt(x).toString(2)
\$\endgroup\$
0
\$\begingroup\$

Ruby -p, 44 bytes

~/^0x[0-9a-fA-F]+$/
$_=$&.hex.to_s 2rescue 0

Attempt This Online!

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

JavaScript (ES6), 116 111 110 bytes

f=
s=>/^0x[\da-f]+$/i.test(s)?s.replace(/./g,c=>parseInt(4+c,36).toString(2).slice(4)).replace(/0+10*(.)/,'$1'):0
<input oninput=o.textContent=f(this.value)><pre id=o>0

Not limited to 53 bits of precision. Edit: Saved 5 bytes by rewriting my digit conversion, which also reduces my language requirements to ES6. Saved 1 byte thanks to @l4m2.

\$\endgroup\$
6
  • \$\begingroup\$ You can reduce the length by 13 bytes by evaluating each character as the hex value. Try it Online \$\endgroup\$ Commented Apr 20, 2017 at 14:23
  • \$\begingroup\$ @fəˈnɛtɪk That doesn't solve the question as posed. \$\endgroup\$
    – Neil
    Commented Apr 20, 2017 at 15:45
  • \$\begingroup\$ Here, I removed leading zeroes from from the first conversion Try it Online still 2 bytes shorter. \$\endgroup\$ Commented Apr 20, 2017 at 16:09
  • \$\begingroup\$ @fəˈnɛtɪk I combined it with Arnauld's answer and got it down to 103: Try it online! \$\endgroup\$
    – Neil
    Commented Apr 20, 2017 at 16:18
  • \$\begingroup\$ @fəˈnɛtɪk Wait, that doesn't work for the fifth test case 0x00101011, sorry. \$\endgroup\$
    – Neil
    Commented Apr 20, 2017 at 16:20
0
\$\begingroup\$

JavaScript (ES6), 109 108 107 bytes

-1 thanks to l4m2

Works for any input size.

s=>/1.*|0$/.exec((/^0x([\da-f]+)$/i.exec(s)||'_0')[1].replace(/./g,d=>(`0x1`+d-0).toString(2).slice(1)))[0]

Try it online!

\$\endgroup\$
7
  • \$\begingroup\$ Hmm ... 2 experienced golfers submitting JS solutions more than twice as long as mine has me wondering if I've missed something in the challenge. \$\endgroup\$
    – Shaggy
    Commented Apr 12, 2017 at 10:58
  • \$\begingroup\$ @Shaggy It all depends on the interpretation of the first line of the challenge. I took it for granted that 'of any size' was a definite requirement -- and so did Neil apparently. \$\endgroup\$
    – Arnauld
    Commented Apr 12, 2017 at 11:04
  • \$\begingroup\$ @Shaggy Just to clarify for everyone: your approach works for up to 0x1fffffffffffff -- aka Number.MAX_SAFE_INTEGER -- and returns rounded results beyond that. By luck, the two large test cases are rounded correctly. \$\endgroup\$
    – Arnauld
    Commented Apr 12, 2017 at 12:22
  • \$\begingroup\$ Huh, I didn't realise that @Shaggy's code worked by accident; I guess I should have counted the distance between the first and last 1 bits in the result. By the way, do you need the $ in the first regexp? \$\endgroup\$
    – Neil
    Commented Apr 12, 2017 at 23:22
  • 1
    \$\begingroup\$ +`0x1${d}` => '0x1'+d-0 \$\endgroup\$
    – l4m2
    Commented Mar 23 at 11:33

Your Answer

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

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