Hexadecimal To Decimal

5

1

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

ralu

Posted 2011-09-29T19:51:47.127

Reputation: 263

Question was closed 2016-04-18T20:15:45.857

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. – Teun Pronk – 2015-02-11T13:27:34.073

1@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? – Álvaro Cuesta – 2012-08-16T06:29:28.100

4I'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)? – user unknown – 2011-09-30T04:56:41.823

You are not allowed any functions that returns or accepts chars/strings except mentioned one. Is that clear? – ralu – 2011-10-01T21:42:28.933

Answers

7

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

Howard

Posted 2011-09-29T19:51:47.127

Reputation: 23 109

With options -ln you mean $_.chars instead of chars probably? – defhlt – 2012-08-16T15:52:07.630

4

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.

hammar

Posted 2011-09-29T19:51:47.127

Reputation: 4 011

3

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

dmckee --- ex-moderator kitten

Posted 2011-09-29T19:51:47.127

Reputation: 2 726

Well, it was introduced in the c99 spec, but you could use long long to guarantee at least 64 bits without library dependence. You could also move the variable declaration to the global scope in order to take advantage of the fact that global variables automatically attain the value of 0 on creation. You can also save 7 characters by putting the &&e>15 condition in to the while loop, getting rid of if(e>15){b=0;break;}, and use e>15?0:b as the number variable for the printf. – Kaslai – 2012-08-16T06:57:18.560

main(c,v)char**v; is 2 shorter than main(int c,char**v) – SeanC – 2012-08-20T18:51:31.083

input 1:2 should return 0 – ralu – 2011-09-30T00:51:01.840

Spoil sport. Pfffsssssththththth...and fixed. – dmckee --- ex-moderator kitten – 2011-09-30T00:58:48.170

2Since you use *d quite often I think you can assign it to a new variable (while(z=*++d)...) and save some chars. – Howard – 2011-09-30T09:31:40.850

Yes. I'd meant to get around to that. – dmckee --- ex-moderator kitten – 2011-09-30T16:34:04.280

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. – Howard – 2011-09-30T17:01:46.223

Oh. That's cute. But you can't combine the ()* form the logic depend on sequence points between each operation (e must get updated). Another "ah!"...you can chain the trinary conditionals. – dmckee --- ex-moderator kitten – 2011-09-30T17:06:35.333

Ah sorry for the confusion. That's what I meant. – Howard – 2011-09-30T17:53:56.703

I don't see anything in your code that depends on the difference between signed and unsigned arithmetic (at least assuming two's complement representation, which seems reasonable enough), so you could just lose the unsigned to save 9 chars. Also, you could use while(e=e>15?b=0:*++d) to get rid of the break. – Ilmari Karonen – 2011-12-06T01:27:51.113

The unsigned was to get the largest available integer space supported by the '89 standard. because 16^8 = 2^32 means that a 32 bit signed integer wouldn't have the range to support the specified input. True, long is a 64 bit value on most modern machines but that isn't guaranteed so I wrote the code to get as close as possible to guaranteeing it consistent with the standard. The while improvement is nice. – dmckee --- ex-moderator kitten – 2011-12-06T02:26:11.103

3

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;
}

Briguy37

Posted 2011-09-29T19:51:47.127

Reputation: 2 616

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) – JiminP – 2012-03-08T12:28:52.613

/[^(0-9|a-f|A-F)]/ -> /[^0-9|a-f|A-F]/ -> /[^0-9|a-f]/i -> /[\W_g-z]/i – Thomas Eding – 2011-10-02T09:40:56.323

return n.match(/regex/)?0:o -> return!/regex/.test(n)&&o – Thomas Eding – 2011-10-02T09:53:02.413

@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! – Briguy37 – 2011-10-03T14:45:29.827

2

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)

migimaru

Posted 2011-09-29T19:51:47.127

Reputation: 1 040

2

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]

Keith Randall

Posted 2011-09-29T19:51:47.127

Reputation: 19 865

2

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.

Samuel Duclos

Posted 2011-09-29T19:51:47.127

Reputation: 21

1you are not following the rules – defhlt – 2012-08-16T06:14:23.420

1

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

ratchet freak

Posted 2011-09-29T19:51:47.127

Reputation: 1 334

1

Mathematica, 64

By the rules:

FromDigits[#-If[#<58,48,If[#<97,55,87]]&/@ToCharacterCode@#,16]&

Mr.Wizard

Posted 2011-09-29T19:51:47.127

Reputation: 2 481

1

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.

CocoaBean

Posted 2011-09-29T19:51:47.127

Reputation: 309

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.

– Martin Ender – 2015-02-11T13:33:39.973

@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. – CocoaBean – 2015-02-11T13:41:30.600

function h(n){return+('0x'+n)||0} does the same in 33 chars. – JP de la Torre – 2018-06-07T01:48:45.343

0

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.

Armand

Posted 2011-09-29T19:51:47.127

Reputation: 499

0

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.

Ben Richards

Posted 2011-09-29T19:51:47.127

Reputation: 291

0

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 ;)

M.Stramm

Posted 2011-09-29T19:51:47.127

Reputation: 101

0

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

daniero

Posted 2011-09-29T19:51:47.127

Reputation: 17 193

0

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.

DavidC

Posted 2011-09-29T19:51:47.127

Reputation: 24 524

0

Perl - 77 chars

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

ardnew

Posted 2011-09-29T19:51:47.127

Reputation: 2 177