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
    \$\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\$ – user unknown Sep 30 '11 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 '11 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\$ – Álvaro Cuesta Aug 16 '12 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 '15 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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ With options -ln you mean $_.chars instead of chars probably? \$\endgroup\$ – defhlt Aug 16 '12 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.

| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ input 1:2 should return 0 \$\endgroup\$ – ralu Sep 30 '11 at 0:51
  • \$\begingroup\$ Spoil sport. Pfffsssssththththth...and fixed. \$\endgroup\$ – dmckee --- ex-moderator kitten Sep 30 '11 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 '11 at 9:31
  • \$\begingroup\$ Yes. I'd meant to get around to that. \$\endgroup\$ – dmckee --- ex-moderator kitten Sep 30 '11 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 '11 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;
}
| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ /[^(0-9|a-f|A-F)]/ -> /[^0-9|a-f|A-F]/ -> /[^0-9|a-f]/i -> /[\W_g-z]/i \$\endgroup\$ – Thomas Eding Oct 2 '11 at 9:40
  • \$\begingroup\$ return n.match(/regex/)?0:o -> return!/regex/.test(n)&&o \$\endgroup\$ – Thomas Eding Oct 2 '11 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 '11 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 '12 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)
| improve this answer | |
\$\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]
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ you are not following the rules \$\endgroup\$ – defhlt Aug 16 '12 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

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Mathematica, 64

By the rules:

FromDigits[#-If[#<58,48,If[#<97,55,87]]&/@ToCharacterCode@#,16]&
| improve this answer | |
\$\endgroup\$
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.

| improve this answer | |
\$\endgroup\$
  • \$\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\$ – Martin Ender Feb 11 '15 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 '15 at 13:41
  • \$\begingroup\$ function h(n){return+('0x'+n)||0} does the same in 33 chars. \$\endgroup\$ – JP de la Torre Jun 7 '18 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.

| improve this answer | |
\$\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.

| improve this answer | |
\$\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 ;)

| improve this answer | |
\$\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

| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

Perl - 77 chars

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

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