5
\$\begingroup\$

Read input of up to 8 characters presented as hexadecimal number and print this number as decimal number. In case that input can not be presented as hexadecimal input it has to print 0

Rules:
It is not allowed to use any function that takes or returns strings/characters, beside function that reads string/char from input and return strings/char as-is, function that takes integer and prints that integer to output as decimal number and function (if needed) that takes character and return its ASCII/UNICODE represented integer.

Shortest code wins

Example input
C0cAc01a

output
3234512922

\$\endgroup\$
4
  • 4
    \$\begingroup\$ I'm not sure whether I understood the rules right; is it: (No fun a except (b, c, d)) or is it (No fun (a, except b), c, d)? \$\endgroup\$ Sep 30, 2011 at 4:56
  • \$\begingroup\$ You are not allowed any functions that returns or accepts chars/strings except mentioned one. Is that clear? \$\endgroup\$
    – ralu
    Oct 1, 2011 at 21:42
  • 1
    \$\begingroup\$ @ralu you should narrow that down. Operators are functions. Methods are functions. If only in/out is accepted, how are we supposed to compute anything? \$\endgroup\$ Aug 16, 2012 at 6:29
  • \$\begingroup\$ So im not quite sure here.. The function tonumber in lua is not allowed or is it? I can do it in 38 characters if thats allowed. \$\endgroup\$
    – Teun Pronk
    Feb 11, 2015 at 13:27

16 Answers 16

7
\$\begingroup\$

Ruby, 74 characters

n=0;p gets.gsub(/./).all?{|x|n=n*16+(x>?9?9:0)+x.ord%16;/[\da-f]/i=~x}?n:0

Input must be given on STDIN. With command line option -ln (counted as 4) it can be shortened to 69 characters.

n=0;p chars.all?{|x|n=n*16+(x>?9?9:0)+x.ord%16;/[\da-f]/i=~x}?n:0
\$\endgroup\$
1
  • \$\begingroup\$ With options -ln you mean $_.chars instead of chars probably? \$\endgroup\$
    – defhlt
    Aug 16, 2012 at 15:52
4
\$\begingroup\$

Haskell, 114 106

x#y=16*x+mod y 16
main=getLine>>=print.maybe 0(foldl(#)0).mapM(`lookup`zip"ABCDEF0123456789abcdef"[-6..])

Handles input of arbitrary size.

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

c -- 181

Input passed on the commandline (one argument only). Relies on K&R function typing defaults. ASCII specific, but has no reliance on the language or library to know how to parse numbers. Lots of characters given up to specifying a large integer type for this purpose.

#include <stdio.h>
main(int c,char**v){unsigned long b=0;char*d=v[1]-1,e;while(e=*++d){
e-=(e>96)?87:(e>64)?55:(e>57)?33:(e>47)?48:0;if(e>15){b=0;break;}
b=b*16+e;}printf("%lu\n",b);}

Ungolfed:

#include <stdio.h>
main(int c,char**v){
  unsigned long b=0;
  char*d=v[1]-1,e;
  while(e=*++d){
    if(e>'`')e-=87; // reduce lowercase letters to 10--
    if(e>'@')e-=55; // reduce uppercase letters to 10--
    if(e>'9')e-=33; // reduce punctioation immediately above the
                      // digits so it does not iterfere
    if(e>'/')e-='0';// reduce digits to 0-9
    if(e>15){b=0;break;} // terminate immediately on bad input
    b=b*16+e;
  }
printf("%lu\n",b);}

Validation:

$ gcc -o dehex dehex_golfed.c 
$ ./dehex C0cAc01a
3234512922
$ ./dehex 1       
1
$ ./dehex 1f
31
$ ./dehex g 
0
$ ./dehex 1g
1
$ ./dehex 1:2
0
\$\endgroup\$
11
  • \$\begingroup\$ input 1:2 should return 0 \$\endgroup\$
    – ralu
    Sep 30, 2011 at 0:51
  • \$\begingroup\$ Spoil sport. Pfffsssssththththth...and fixed. \$\endgroup\$ Sep 30, 2011 at 0:58
  • 2
    \$\begingroup\$ Since you use *d quite often I think you can assign it to a new variable (while(z=*++d)...) and save some chars. \$\endgroup\$
    – Howard
    Sep 30, 2011 at 9:31
  • \$\begingroup\$ Yes. I'd meant to get around to that. \$\endgroup\$ Sep 30, 2011 at 16:34
  • \$\begingroup\$ Just saw another one you may use for each if: if(e>96)e-=87; => e-=e>96?87:0; or if you like e-=(e>96)*87;. With latter you can also combine all those ifs into one expression. \$\endgroup\$
    – Howard
    Sep 30, 2011 at 17:01
3
\$\begingroup\$

JavaScript, 127 119 characters (thanks trinithis!)

Code-Golfed:

function f(n){for(o=i=0,c=1;l=n[i++];)o*=16,l=l.charCodeAt(0),o+=l-(l>96?87:l>64?55:48);return /[\W_g-z]/i.test(n)?0:o}

Formatted:

function hexToDec(hexChars) {
    //Iterate through hex chars
    for (dec=i=0,count = 1; hexChar = hexChars[i++];) {
        dec *= 16;
        hexCharCode = hexChar.charCodeAt(0);

        //Get the hex number and add it
        hex = hexCharCode;
        if(hexCharCode > 96){
            hex -= 87;//For lower case letters
        } else if (hexCharCode > 64){
            hex -= 55;//For upper case letters
        } else {
            hex -= 48;//For numbers
        }
        dec += hex;
    }

    //Return 0 if invalid, decimal value otherwise
    if(/[\W_g-z]/i.test(hexChars)){
        return 0;
    }
    return dec;
}
\$\endgroup\$
4
  • \$\begingroup\$ /[^(0-9|a-f|A-F)]/ -> /[^0-9|a-f|A-F]/ -> /[^0-9|a-f]/i -> /[\W_g-z]/i \$\endgroup\$ Oct 2, 2011 at 9:40
  • \$\begingroup\$ return n.match(/regex/)?0:o -> return!/regex/.test(n)&&o \$\endgroup\$ Oct 2, 2011 at 9:53
  • \$\begingroup\$ @trinithis: Thanks much, you are a regex-rockstar! For the second one, I changed match to test, but decided to keep the original flow so it would return 0 instead of false for bad hex numbers (saved 1 char instead of 2). Thanks again! \$\endgroup\$
    – Briguy37
    Oct 3, 2011 at 14:45
  • \$\begingroup\$ o=i=0,c=1 -> o=i=0, /[\W_g-z]/i.test(n)?0:o -> o*!/[\W_g-z]/i.test(n), o*=16,l=l.charCodeAt(0),o+=l-(l>96?87:l>64?55:48) -> o=o*16+(l=l.charCodeAt(0))-(l>96?87:l>64?55:48) \$\endgroup\$
    – JiminP
    Mar 8, 2012 at 12:28
2
\$\begingroup\$

Ruby 1.9 (84)

gets.chomp!;n=0;p~/[^0-9A-Fa-f]/?0:($_.chars{|c|o=c.ord-48;n=16*n+(o>9?o%32-7:o)};n)

If we're allowed to use command line options, this is shortened to 72 characters + 4 for -ln:

n=0;p~/[^0-9A-Fa-f]/?0:($_.chars{|c|o=c.ord-48;n=16*n+(o>9?o%32-7:o)};n)
\$\endgroup\$
2
\$\begingroup\$

Python, 106 characters

n=0
e=9e9
for c in raw_input():n=n*16+ord(c)-[e,48,e,55,e,87,e][sum(c>x for x in'/9@F`f')]
print[n,0][n<0]
\$\endgroup\$
2
\$\begingroup\$

Scheme, 24 chars

(string->number(read)16)

I hope this is not considered cheating. If it is:

(string->number(string-append "#x"(read)))

String to number conversion is mandatory.

In Scheme, if your program is not simple, something is wrong and you should start over until it is made simple. Scheme's power relies on removing restrictions instead of adding features so that the language can be easily extended. Scheme is, with Lisp-derived languages, a programmable programming language.

\$\endgroup\$
1
  • 1
    \$\begingroup\$ you are not following the rules \$\endgroup\$
    – defhlt
    Aug 16, 2012 at 6:14
1
\$\begingroup\$

D 194 chars

void main(string[] a){ulong r;foreach(c;a[1]){switch(c){case '0'..'9':r+=c-'0';break;case 'a'..'f':r+=c-'a'+10;break;case 'A'..'F':r+=c-'A'+10;break;default: write(0); return;}r*=16;}write(r);}

I could get some profit by replacing the char literals with the numerals and get thus get rid of the +10 for the a-f but this doesn't depend on char encoding though D defines ascii support IIRC

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

Mathematica, 64

By the rules:

FromDigits[#-If[#<58,48,If[#<97,55,87]]&/@ToCharacterCode@#,16]&
\$\endgroup\$
0
1
\$\begingroup\$

JavaScript, 48 chars

function h(n){return 0/0==+("0x"+n)?0:+("0x"+n)}

Formatted + Uncompressed

function h(n){
    if(+("0x"+n)==NaN) {
        return 0;
    }
    else {
        return +("0x"+n);
    }
}

The plus operator set before a string converts it into a decimal number. So I just had to prepend a "0x" and return 0 if it isn't a valid number to conform the rules.

\$\endgroup\$
3
  • \$\begingroup\$ Arguably, operators are just shorthand built-in functions, so in a way this is violating the rule "It is not allowed to use any function that takes or returns strings/characters". We also have two standard loopholes for these kinds of terminology quibbles. \$\endgroup\$ Feb 11, 2015 at 13:33
  • \$\begingroup\$ @MartinBüttner JavaScript's plus operator is not intended to convert int to string. The language just automatically converts the string to an int because it saw the plus. Also there is no builtin function to add two numbers. \$\endgroup\$
    – CocoaBean
    Feb 11, 2015 at 13:41
  • \$\begingroup\$ function h(n){return+('0x'+n)||0} does the same in 33 chars. \$\endgroup\$ Jun 7, 2018 at 1:48
0
\$\begingroup\$

Groovy, 74

i={it.inject(0){a,v->a*16L+('0123456789abcdef'.indexOf(v.toLowerCase()))}}

test case:

assert 3234512922 == i('C0cAc01a')

Not sure I understood the rules, though.

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

Perl, 39 characters

print<>=~m/^[[:xdigit:]]{1,8}$/?hex$&:0

I kind of feel weird doing it this way in Perl but I believe it follows the rules, since the hex() function is a language construct and not a library function. If not...

Perl, 64 characters

print<>!~m/^[[:xdigit:]]{1,8}$/?0:unpack 'L',reverse pack'H8',$&

I hope is fine.

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

C# - 192 189

oldschool, uses Console arguments for input, Console.WriteLine() for output. could possibly save a few chars, but can't get rid of most lengthy keywords. Makes evil use of foreach, ternary operator madness, bitwise complement ~ and signedness. Reads any length input and aborts on bad characters ([^0-9a-fA-F]).

namespace _{class _{static void Main(string[]a){long b=0;foreach(int c in a.Length>0?a[0]:"")b=b<<4|(c-'0'<10?c-'0':c-'A'<6?c-'A'+10:c-'a'<6?c-'a'+10:~0L);System.Console.Write(b<0?0:b);}}}

A little deobfuscated (old ver):

using System;
namespace CodeGolf
{
    class Program
    {
        static void Main()
        {
            long ret = 0;
            int nextChar;

            while ((nextChar = Console.Read()) != '\r')
            {
                ret <<= 4;
                ret |= nextChar - '0' < 10 ? 
                        nextChar - '0' : 
                        nextChar - 'A' < 6 ? 
                            nextChar - 'A' + 10 : 
                            nextChar - 'a' < 6 ? 
                                nextChar - 'a' + 10 : 
                                ~0L;
            }

            Console.WriteLine(ret < 0 ? 0 : ret);
        }
    }
}

Would love to see a C# implementation in hardcore MSIL ;)

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

Python, 98 chars

print sum(16**n*i for i,n in zip(((ord(c)|32)-[48,87][c>'9']for c in raw_input()[::-1]),range(9)))

A one-liner with the nifty bonus that you can use characters > 'f' for shorthand notation, e.g 'g' counts for 16, 'h' for 17 etc :D

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

Mathematica 93 92 chars

Fold[16 #1 + #2 &, 0,ToExpression[Characters@n /. Thread@Rule["a"~CharacterRange~"f", 10~Range~15]]]

Not as streamlined as Mr.Wizard's answer, but I'll include it for variety. It makes use of no native base conversion routines. There is a shortcoming in my answer: I assumed that characters a to f would be given in lowercase.

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

Perl - 77 chars

@h{0..9,'a'..'f'}=0..15;$n+=$h{lc$_}*16**($a++-1)for reverse split//,<>;say$n
\$\endgroup\$

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