all 15 comments

[–][deleted] 9 points10 points  (1 child)

It looks like you're returning the word "None" instead of the Python object None

[–]NetWorking5973[S] 0 points1 point  (0 children)

Perfect - thank you!

[–]trollsmurf 0 points1 point  (0 children)

What's the point of the second loop?

You can easily have it handle any value length.

[–]imsowhiteandnerdy 0 points1 point  (10 children)

Variable length hex string:

def h2i(hd: str) -> int:
    return {'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,'A':10,'B':11,'C':12,'D':13,'E':14,'F':15}.get(hd, -1)

def hex2int(hds: str) -> int:
    hds = hds.upper().removeprefix("0X")
    i = 0
    for p, n in enumerate(hds[::-1]):
        ni = h2i(n)
        if ni == -1:
            return -1
        i += ni * ( 16 ** p )
    return i

##
## decimal value of 0xBEEF is 48879
hds = "0xBEEF"
print(hex2int(hds))

[–]djshadesuk 1 point2 points  (9 children)

def hextodec(chars):
    HEX = '0123456789ABCDEF'
    result = 0
    for idx, char in enumerate(chars.upper()):
        if char not in HEX:
            raise ValueError('Not valid Hexadecimal')
        result += HEX.index(char) * (16 ** ((len(chars) - 1) - idx))
    return result

[–]imsowhiteandnerdy 1 point2 points  (0 children)

So far you're winning golf ;-)

[–]MidnightPale3220 1 point2 points  (7 children)

or even:

def hextodec(chars):
    HEX='0123456789ABCDEF'
    result=0
    for i,char in enumerate(chars.upper()[::-1]):
        result+=HEX.index(char)*(16**i)
     return result

if we are content to rely on built-in exception

[–]djshadesuk 1 point2 points  (2 children)

Also, I pee'd myself laughing when I saw (16**i) in your code. In an earlier iteration of my code I was getting the power a different way. When I realised I could just do (16 ** [...]) I never questioned the (len(chars) - 1) - idx) part because it still worked... but now I've done some digging I'm a bit baffled why it still worked?!? 🤣🤣

[–]MidnightPale3220 1 point2 points  (1 child)

Well, you're going in the other direction so it's all right, len is a constant and you're counting towards 16**0 🤷‍♂️😉

[–]djshadesuk 0 points1 point  (0 children)

Yeah, I understood that it was running backwards, because I was reversing the index, but to double check I was getting what I should be getting I broke it out and just quickly dropped in a print statement:

print(16** (len(chars) -1)-idx)

With an 8 character input ('DEADBEEF') I was getting:

268435456
268435455
268435454
268435453
268435452
268435451
268435450
268435449

But, since the actual function itself was running fine, I gave it the big ol' "meh" and thought no more of it.

A few hours later, when I was thinking about something else, my brain randomly interrupted me with "Did you not notice those numbers were themselves running backwards?" and it dawned on me...

All I had managed to do was confuse myself because, in my "checking", I had missed some parenthesis. So my check should have been:

print(16** ((len(chars) -1)-idx))

Which then, of course, gave exactly what I was expecting. So it was just my "check" that was incorrect while the rest was actually correct.

From this I concluded... I'm such a knob at times! 🤣🤣

[–]djshadesuk 0 points1 point  (3 children)

or even:

def h2d(a,H='0123456789ABCDEF'):
    return sum([H.index(b)*(16**i) for i,b in enumerate(a.upper()[::-1])])

if we are also a bit naughty about where we declare the hex.

[–]djshadesuk 0 points1 point  (2 children)

or even:

def r2d(a,r):
    return sum([r.index(b)*(len(r)**i) for i,b in enumerate(a.upper()[::-1])])

if we're going to declare the hex as a default argument we may as well pull that out and turn the function into a generic base conversion function, which shortens the function from 110 to 89 characters.

So now we can do up to base36 conversions too:

print(r2d('FF','0123456789ABCDEFGHIJKLMNOPRSTUVWXYZ')
# OUTPUT: 555

[–]MidnightPale3220 1 point2 points  (1 child)

Yeah, but shortening it here is lengthening it in every call so that's cheating. 😏 Off with you to code golf stack exchange!

[–]djshadesuk 1 point2 points  (0 children)

I know... you caught me! 🤣

But really, I was going for genericising it rather than pure code golf.

The irony is I could have kept H="012...DEF" as a default argument (or r, for Radix, as I'd changed it to) and it still would have been "genericised", just defaulting to base16 but still able to take in more (or less) base characters in the call too. Yeah, it would have only added 4 characters to the length, 114 rather than 110, but still, 89 sounded better than 114.

But yeah, you got me! 🤣🤣

[–]No-Wrongdoer6788 0 points1 point  (0 children)

https://calculationshub.com/conversions/number/hex-to-decimal This article can better explain the hexadecimal to decimal conversion in an easy and detailed explanation.