decimal to hex converter function (python) - python

So this is the code and dictionary I have created:
def dectohex (number, dectohex_table):
final_dectohex=''
if number in dectohex_table:
final_dectohex+=dectohex_table[number]
print(final_dectohex)
dectohex_table={'0':'0', '1':'1', '2':'2', '3':'3', '4':'4', '5':'5', '6':'6', '7':'7', '8':'8', '9':'9', '10':'A', '11':'B', '12':'C', '13':'D'
, '14':'E', '15':'F'}
Is there a way to use this code using the dictionary (since we must) but to convert numbers higher than 15?

I'm guessing this is homework (since python has a hex function built-in)
What you should look into is the modulo operation % and loops :)
I don't want to spell it out but think about how you would break a base 16 number using modulo..
HINT:
Try the following:
print(423 % 10)
print( (423/10) % 10)
print( ((423/10)/10) % 10)

table = {0:'0', 1:'1', 2:'2', 3:'3', 4:'4', 5:'5', 6:'6', 7:'7', 8:'8', 9:'9', 10:'A', 11:'B', 12:'C', 13:'D', 14:'E', 15:'F'}
def dectohex(num, tab):
value = num
s = ''
while value > 0:
s += table[value % 16]
value //= 16
return '0x' + ''.join(reversed(s))
>>> dectohex(123456, table) # the above function
'0x1E240'
>>> hex(123456) # python's function
'0x1e240'

Turn this one-liner in ..
>>> x=423
>>> ''.join([ {'0000':'0','0001':'1','0010':'2','0011':'3','0100':'4','0101':'5',
'0110':'6','0111':'7','1000':'8','1001':'9','1010':'a','1011':'b',
'1100':'c','1101':'d','1110':'e','1111':'f'}[y]
for y in re.findall('....', ''.join(map(str, [ int(x&(1<<i)>0)
for i in range(32) ][::-1]))) ])
'000001a7'

Related

Format a large integer with commas without using .format()

I'm trying to format any number by inserting ',' every 3 numbers from the end by not using format()
123456789 becomes 123,456,789
1000000 becomes 1,000,000
What I have so far only seems to go from the start, I've tried different ideas to get it to reverse but they seem to not work as I hoped.
def format_number(number):
s = [x for x in str(number)]
for a in s[::3]:
if s.index(a) is not 0:
s.insert(s.index(a), ',')
return ''.join(s)
print(format_number(1123456789))
>> 112,345,678,9
But obviously what I want is 1,123,456,789
I tried reversing the range [:-1:3] but I get 112,345,6789
Clarification: I don't want to use format to structure the number, I'd prefer to understand how to do it myself just for self-study's sake.
Here is a solution for you, without using built-in functions:
def format_number(number):
s = list(str(number))[::-1]
o = ''
for a in range(len(s)):
if a and a % 3 == 0:
o += ','
o += s[a]
return o[::-1]
print(format_number(1123456789))
And here is the same solution using built-in functions:
def format_number(number):
return '{:,}'.format(number)
print(format_number(1123456789))
I hope this helps. :D
One way to do it without built-in functions at all...
def format_number(number):
i = 0
r = ""
while True:
r = "0123456789"[number % 10] + r
number //= 10
if number == 0:
return r
i += 1
if i % 3 == 0:
r = "," + r
Here's a version that's almost free of built-in functions or methods (it does still have to use str)
def format_number(number):
i = 0
r = ""
for character in str(number)[::-1]:
if i > 0 and i % 3 == 0:
r = "," + r
r = character + r
i += 1
return r
Another way to do it without format but with other built-ins is to reverse the number, split it into chunks of 3, join them with a comma, and reverse it again.
def format_number(number):
backward = str(number)[::-1]
r = ",".join(backward[i:i+3] for i in range(0, len(backward), 3))
return r[::-1]
Your current approach has following drawbacks
checking for equality/inequality in most cases (especially for int) should be made using ==/!= operators, not is/is not ones,
using list.index returns first occurence from the left end (so s.index('1') will be always 0 in your example), we can iterate over range if indices instead (using range built-in).
we can have something like
def format_number(number):
s = [x for x in str(number)]
for index in range(len(s) - 3, 0, -3):
s.insert(index, ',')
return ''.join(s)
Test
>>> format_number(1123456789)
'1,123,456,789'
>>> format_number(6789)
'6,789'
>>> format_number(135)
'135'
If range, list.insert and str.join are not allowed
We can replace
range with while loop,
list.insert using slicing and concatenation,
str.join with concatenation,
like
def format_number(number):
s = [x for x in str(number)]
index = len(s) - 3
while index > 0:
s = s[:index] + [','] + s[index:]
index -= 3
result = ''
for character in s:
result += character
return result
Using str.format
Finally, following docs
The ',' option signals the use of a comma for a thousands separator. For a locale aware separator, use the 'n' integer presentation type instead.
your function can be simplified to
def format_number(number):
return '{:,}'.format(number)
and it will even work for floats.

Python (lambda?) random number generation

I have a string where I want to output random ints of differing size using Python's built-in format function.
IE: "{one_digit}:{two_digit}:{one_digit}"
Yields: "3:27:9"
I'm trying:
import random
"{one_digit}:{two_digit}:{one_digit}".format(one_digit=random.randint(1,9),two_digits=random.randint(10,99))
but this always outputs...
"{one_digit}:{two_digit}:{one_digit}".format(one_digit=random.randint(1,9),two_digit=random.randint(10,99))
>>>'4:22:4'
"{one_digit}:{two_digit}:{one_digit}".format(one_digit=random.randint(1,9),two_digit=random.randint(10,99))
>>>'7:48:7'
"{one_digit}:{two_digit}:{one_digit}".format(one_digit=random.randint(1,9),two_digit=random.randint(10,99))
>>>'2:28:2'
"{one_digit}:{two_digit}:{one_digit}".format(one_digit=random.randint(1,9),two_digit=random.randint(10,99))
>>>'1:12:1'
Which is as expected since the numbers are evaluated before hand. I'd like them to all be random, though. I tried using a lambda function but only got this:
"test{number}:{number}".format(number=lambda x: random.randint(1,10))
But that only yields
"test{number}:{number}".format(number=lambda x: random.randint(1,10))
>>>'test<function <lambda> at 0x10aa14e18>:<function <lambda> at 0x10aa14e18>'
First off: str.format is the wrong tool for the job, because it doesn't allow you to generate a different value for each replacement.
The correct solution is therefore to implement your own replacement function. We'll replace the {one_digit} and {two_digit} format specifiers with something more suitable: {1} and {2}, respectively.
format_string = "{1}:{2}:{1}"
Now we can use regex to substitute all of these markers with random numbers. Regex is handy because re.sub accepts a replacement function, which we can use to generate a new random number every time:
import re
def repl(match):
num_digits = int(match.group(1))
lower_bound = 10 ** (num_digits - 1)
upper_bound = 10 * lower_bound - 1
random_number = random.randint(lower_bound, upper_bound)
return str(random_number)
result = re.sub(r'{(\d+)}', repl, format_string)
print(result) # result: 5:56:1
How about this?
import random
r = [1,2,3,4,5]
','.join(map(str,(random.randint(-10**i,10**i) for i in r)))
The first two params(-10** i, 10**i) are low and upper bound meanwhile size=10 is the amount of numbers).
Example output: '-8,45,-328,7634,51218'
Explanation:
It seems you are looking to join random numbers with ,. This can simply be done using ','.join([array with strings]), e.g. ','.join(['1','2']) which would return '1,2'.
What about This?
'%s:%s:%s' % (random.randint(1,9),random.randint(10,99),random.randint(1,9))
EDIT : meeting requirements.
a=[1,2,2,1,3,4,5,9,0] # our definition of the pattern (decimal range)
b= ''
for j in enumerate(a):
x=random.randint(10**j,10**(j+1)-1)
b = b + '%s:' % x
print(b)
sample:
print (b)
31:107:715:76:2602:99021:357311:7593756971:1:

How do I add each individual character of a variable

I can work out how to add the two characters together, for example, 9+9 would return 8 rather than 18 (if that makes sense)
I need to make it work for 8 characters of two separate variables.
Here is the one character version:
def code_digit(n, key):
result = n + key
mod = result%10
print (mod)
>>> code_digit(9,9)
8
Can you simplify the answer as much as possible, I am a beginner in python, thanks.
I understand there seems to be no goal, but it's for an assignment in my programming class.
It should return the sum of two numbers, wrapped round if it exceeds 9, so for example:
9+9 = (1)8
9+7 = (1)6
7+7 = (1)4
5+5 = (1)0
Ignore the brackets!
The final code should work like this...
>>> code_block(’12341234’,’12121212’)
’24462446’
>>> code_block(’66554433’,’44556677’)
’00000000’
Okay, we’re reusing your code_digit function, just a bit simplified and make it return the result instead of printing it, and also make it accept strings:
def code_digit(n, key):
return (int(n) + int(key)) % 10
def code_block(num1, num2):
n1, n2 = str(num1), str(num2)
return ''.join(map(str, [code_digit(d1, d2) for d1, d2 in zip(n1, n2)]))
And it works!
>>> code_block(12341234, 12121212)
'24462446'
>>> code_block(66554433, 44556677)
'00000000'
But I’m not done yet. We can make this a bit more complex by allowing an arbitrary number of numbers:
def code_digits(*digits):
return sum(map(int, digits)) % 10
def code_blocks(*blocks):
return ''.join(map(str, (code_digits(*digits) for digits in zip(*map(str, blocks)))))
>>> code_blocks(123, 124, 457)
'694'
>>> code_blocks(1234, 5678, 9012, 3456)
'8260'
And want to support numbers with unequal lengths too (i.e. 6 and 15, interpreted as 06 and 15)? Sure.
from itertools import izip_longest
def code_blocks(*blocks):
return ''.join(reversed(list(map(str, (code_digits(*digits) for digits in zip_longest(*map(reversed, map(str, blocks)), fillvalue='0'))))))
>>> code_blocks(6, 15)
'11'
>>> code_blocks(123, 12, 235, 346, 45457)
'45053'
OK! Now I know what you're asking for!
def code_digit(n, key):
remainder = (n+key)/10
mod = (n+key)%10
print "(%s)%s"%(remainder, mod)
At some point somethings might can become too pythonic, but if I understand what you doing this should work:
def code_digit(aStr, bStr):
return ''.join([ str((int(x[0]) + int(x[1]))%10) for x in zip(aStr, bStr)])

Converting integer to digit list [duplicate]

This question already has answers here:
How to split an integer into a list of digits?
(10 answers)
Closed 4 months ago.
What is the quickest and cleanest way to convert an integer into a list?
For example, change 132 into [1,3,2] and 23 into [2,3]. I have a variable which is an int, and I want to be able to compare the individual digits so I thought making it into a list would be best, since I can just do int(number[0]), int(number[1]) to easily convert the list element back into int for digit operations.
Convert the integer to string first, and then use map to apply int on it:
>>> num = 132
>>> map(int, str(num)) #note, This will return a map object in python 3.
[1, 3, 2]
or using a list comprehension:
>>> [int(x) for x in str(num)]
[1, 3, 2]
There are already great methods already mentioned on this page, however it does seem a little obscure as to which to use. So I have added some mesurements so you can more easily decide for yourself:
A large number has been used (for overhead) 1111111111111122222222222222222333333333333333333333
Using map(int, str(num)):
import timeit
def method():
num = 1111111111111122222222222222222333333333333333333333
return map(int, str(num))
print(timeit.timeit("method()", setup="from __main__ import method", number=10000)
Output: 0.018631496999999997
Using list comprehension:
import timeit
def method():
num = 1111111111111122222222222222222333333333333333333333
return [int(x) for x in str(num)]
print(timeit.timeit("method()", setup="from __main__ import method", number=10000))
Output: 0.28403817900000006
Code taken from this answer
The results show that the first method involving inbuilt methods is much faster than list comprehension.
The "mathematical way":
import timeit
def method():
q = 1111111111111122222222222222222333333333333333333333
ret = []
while q != 0:
q, r = divmod(q, 10) # Divide by 10, see the remainder
ret.insert(0, r) # The remainder is the first to the right digit
return ret
print(timeit.timeit("method()", setup="from __main__ import method", number=10000))
Output: 0.38133582499999996
Code taken from this answer
The list(str(123)) method (does not provide the right output):
import timeit
def method():
return list(str(1111111111111122222222222222222333333333333333333333))
print(timeit.timeit("method()", setup="from __main__ import method", number=10000))
Output: 0.028560138000000013
Code taken from this answer
The answer by Duberly González Molinari:
import timeit
def method():
n = 1111111111111122222222222222222333333333333333333333
l = []
while n != 0:
l = [n % 10] + l
n = n // 10
return l
print(timeit.timeit("method()", setup="from __main__ import method", number=10000))
Output: 0.37039988200000007
Code taken from this answer
Remarks:
In all cases the map(int, str(num)) is the fastest method (and is therefore probably the best method to use). List comprehension is the second fastest (but the method using map(int, str(num)) is probably the most desirable of the two.
Those that reinvent the wheel are interesting but are probably not so desirable in real use.
The shortest and best way is already answered, but the first thing I thought of was the mathematical way, so here it is:
def intlist(n):
q = n
ret = []
while q != 0:
q, r = divmod(q, 10) # Divide by 10, see the remainder
ret.insert(0, r) # The remainder is the first to the right digit
return ret
print intlist(3)
print '-'
print intlist(10)
print '--'
print intlist(137)
It's just another interesting approach, you definitely don't have to use such a thing in practical use cases.
n = int(raw_input("n= "))
def int_to_list(n):
l = []
while n != 0:
l = [n % 10] + l
n = n // 10
return l
print int_to_list(n)
If you have a string like this: '123456'
and you want a list of integers like this: [1,2,3,4,5,6], use this:
>>>s = '123456'
>>>list1 = [int(i) for i in list(s)]
>>>print(list1)
[1,2,3,4,5,6]
or if you want a list of strings like this: ['1','2','3','4','5','6'], use this:
>>>s = '123456'
>>>list1 = list(s)
>>>print(list1)
['1','2','3','4','5','6']
Use list on a number converted to string:
In [1]: [int(x) for x in list(str(123))]
Out[2]: [1, 2, 3]
>>>list(map(int, str(number))) #number is a given integer
It returns a list of all digits of number.
you can use:
First convert the value in a string to iterate it, Them each value can be convert to a Integer value = 12345
l = [ int(item) for item in str(value) ]
By looping it can be done the following way :)
num1= int(input('Enter the number'))
sum1 = num1 #making a alt int to store the value of the orginal so it wont be affected
y = [] #making a list
while True:
if(sum1==0):#checking if the number is not zero so it can break if it is
break
d = sum1%10 #last number of your integer is saved in d
sum1 = int(sum1/10) #integer is now with out the last number ie.4320/10 become 432
y.append(d) # appending the last number in the first place
y.reverse()#as last is in first , reversing the number to orginal form
print(y)
Answer becomes
Enter the number2342
[2, 3, 4, 2]
num = 123
print(num)
num = list(str(num))
num = [int(i) for i in num]
print(num)
num = list(str(100))
index = len(num)
while index > 0:
index -= 1
num[index] = int(num[index])
print(num)
It prints [1, 0, 0] object.
Takes an integer as input and converts it into list of digits.
code:
num = int(input())
print(list(str(num)))
output using 156789:
>>> ['1', '5', '6', '7', '8', '9']

Encoding a numeric string into a shortened alphanumeric string, and back again

Quick question. I'm trying to find or write an encoder in Python to shorten a string of numbers by using upper and lower case letters. The numeric strings look something like this:
20120425161608678259146181504021022591461815040210220120425161608667
The length is always the same.
My initial thought was to write some simple encoder to utilize upper and lower case letters and numbers to shorten this string into something that looks more like this:
a26Dkd38JK
That was completely arbitrary, just trying to be as clear as possible.
I'm certain that there is a really slick way to do this, probably already built in. Maybe this is an embarrassing question to even be asking.
Also, I need to be able to take the shortened string and convert it back to the longer numeric value.
Should I write something and post the code, or is this a one line built in function of Python that I should already know about?
Thanks!
This is a pretty good compression:
import base64
def num_to_alpha(num):
num = hex(num)[2:].rstrip("L")
if len(num) % 2:
num = "0" + num
return base64.b64encode(num.decode('hex'))
It first turns the integer into a bytestring and then base64 encodes it. Here's the decoder:
def alpha_to_num(alpha):
num_bytes = base64.b64decode(alpha)
return int(num_bytes.encode('hex'), 16)
Example:
>>> num_to_alpha(20120425161608678259146181504021022591461815040210220120425161608667)
'vw4LUVm4Ea3fMnoTkHzNOlP6Z7eUAkHNdZjN2w=='
>>> alpha_to_num('vw4LUVm4Ea3fMnoTkHzNOlP6Z7eUAkHNdZjN2w==')
20120425161608678259146181504021022591461815040210220120425161608667
There are two functions that are custom (not based on base64), but produce shorter output:
chrs = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
l = len(chrs)
def int_to_cust(i):
result = ''
while i:
result = chrs[i % l] + result
i = i // l
if not result:
result = chrs[0]
return result
def cust_to_int(s):
result = 0
for char in s:
result = result * l + chrs.find(char)
return result
And the results are:
>>> int_to_cust(20120425161608678259146181504021022591461815040210220120425161608667)
'9F9mFGkji7k6QFRACqLwuonnoj9SqPrs3G3fRx'
>>> cust_to_int('9F9mFGkji7k6QFRACqLwuonnoj9SqPrs3G3fRx')
20120425161608678259146181504021022591461815040210220120425161608667L
You can also shorten the generated string, if you add other characters to the chrs variable.
Do it with 'class':
VALID_CHRS = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
BASE = len(VALID_CHRS)
MAP_CHRS = {k: v
for k, v in zip(VALID_CHRS, range(BASE + 1))}
class TinyNum:
"""Compact number representation in alphanumeric characters."""
def __init__(self, n):
result = ''
while n:
result = VALID_CHRS[n % BASE] + result
n //= BASE
if not result:
result = VALID_CHRS[0]
self.num = result
def to_int(self):
"""Return the number as an int."""
result = 0
for char in self.num:
result = result * BASE + MAP_CHRS[char]
return result
Sample usage:
>> n = 4590823745
>> tn = TinyNum(a)
>> print(n)
4590823745
>> print(tn.num)
50GCYh
print(tn.to_int())
4590823745
(Based on Tadeck's answer.)
>>> s="20120425161608678259146181504021022591461815040210220120425161608667"
>>> import base64, zlib
>>> base64.b64encode(zlib.compress(s))
'eJxly8ENACAMA7GVclGblv0X4434WrKFVW5CtJl1HyosrZKRf3hL5gLVZA2b'
>>> zlib.decompress(base64.b64decode(_))
'20120425161608678259146181504021022591461815040210220120425161608667'
so zlib isn't real smart at compressing strings of digits :(

Categories

Resources