How do I add each individual character of a variable - python

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

Related

decimal to hex converter function (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'

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']

Python: How to generate a 12-digit random number?

In Python, how to generate a 12-digit random number? Is there any function where we can specify a range like random.range(12)?
import random
random.randint()
The output should be a string with 12 digits in the range 0-9 (leading zeros allowed).
Whats wrong with a straightforward approach?
>>> import random
>>> random.randint(100000000000,999999999999)
544234865004L
And if you want it with leading zeros, you need a string.
>>> "%0.12d" % random.randint(0,999999999999)
'023432326286'
Edit:
My own solution to this problem would be something like this:
import random
def rand_x_digit_num(x, leading_zeroes=True):
"""Return an X digit number, leading_zeroes returns a string, otherwise int"""
if not leading_zeroes:
# wrap with str() for uniform results
return random.randint(10**(x-1), 10**x-1)
else:
if x > 6000:
return ''.join([str(random.randint(0, 9)) for i in xrange(x)])
else:
return '{0:0{x}d}'.format(random.randint(0, 10**x-1), x=x)
Testing Results:
>>> rand_x_digit_num(5)
'97225'
>>> rand_x_digit_num(5, False)
15470
>>> rand_x_digit_num(10)
'8273890244'
>>> rand_x_digit_num(10)
'0019234207'
>>> rand_x_digit_num(10, False)
9140630927L
Timing methods for speed:
def timer(x):
s1 = datetime.now()
a = ''.join([str(random.randint(0, 9)) for i in xrange(x)])
e1 = datetime.now()
s2 = datetime.now()
b = str("%0." + str(x) + "d") % random.randint(0, 10**x-1)
e2 = datetime.now()
print "a took %s, b took %s" % (e1-s1, e2-s2)
Speed test results:
>>> timer(1000)
a took 0:00:00.002000, b took 0:00:00
>>> timer(10000)
a took 0:00:00.021000, b took 0:00:00.064000
>>> timer(100000)
a took 0:00:00.409000, b took 0:00:04.643000
>>> timer(6000)
a took 0:00:00.013000, b took 0:00:00.012000
>>> timer(2000)
a took 0:00:00.004000, b took 0:00:00.001000
What it tells us:
For any digit under around 6000 characters in length my method is faster - sometimes MUCH faster, but for larger numbers the method suggested by arshajii looks better.
Do random.randrange(10**11, 10**12). It works like randint meets range
From the documentation:
randrange(self, start, stop=None, step=1, int=<type 'int'>, default=None, maxwidth=9007199254740992L) method of random.Random instance
Choose a random item from range(start, stop[, step]).
This fixes the problem with randint() which includes the
endpoint; in Python this is usually not what you want.
Do not supply the 'int', 'default', and 'maxwidth' arguments.
This is effectively like doing random.choice(range(10**11, 10**12)) or random.randint(10**1, 10**12-1). Since it conforms to the same syntax as range(), it's a lot more intuitive and cleaner than these two alternatives
If leading zeros are allowed:
"%012d" %random.randrange(10**12)
Since leading zeros are allowed (by your comment), you could also use:
int(''.join(str(random.randint(0,9)) for _ in xrange(12)))
EDIT: Of course, if you want a string, you can just leave out the int part:
''.join(str(random.randint(0,9)) for _ in xrange(12))
This seems like the most straightforward way to do it in my opinion.
There are many ways to do that:
import random
rnumber1 = random.randint(10**11, 10**12-1) # randint includes endpoint
rnumber2 = random.randrange(10**11, 10**12) # randrange does not
# useful if you want to generate some random string from your choice of characters
digits = "123456789"
digits_with_zero = digits + "0"
rnumber3 = random.choice(digits) + ''.join(random.choice(digits_with_zero) for _ in range(11))
from random import randint
def random_with_N_digits(n):
range_start = 10**(n-1)
range_end = (10**n)-1
return randint(range_start, range_end)
print random_with_N_digits(12)
This may not be exactly what you're looking for, but a library like rstr let's you generate random strings. With that all you would need is (leading 0 allowed):
import rstr
foo = rstr.digits(12)

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 :(

Split string by count of characters

I can't figure out how to do this with string methods:
In my file I have something like 1.012345e0070.123414e-004-0.1234567891.21423... which means there is no delimiter between the numbers.
Now if I read a line from this file I get a string like above which I want to split after e.g. 12 characters.
There is no way to do this with something like str.split() or any other string method as far as I've seen but maybe I'm overlooking something?
Thx
Since you want to iterate in an unusual way, a generator is a good way to abstract that:
def chunks(s, n):
"""Produce `n`-character chunks from `s`."""
for start in range(0, len(s), n):
yield s[start:start+n]
nums = "1.012345e0070.123414e-004-0.1234567891.21423"
for chunk in chunks(nums, 12):
print chunk
produces:
1.012345e007
0.123414e-00
4-0.12345678
91.21423
(which doesn't look right, but those are the 12-char chunks)
You're looking for string slicing.
>>> x = "1.012345e0070.123414e-004-0.1234567891.21423"
>>> x[2:10]
'012345e0'
line = "1.012345e0070.123414e-004-0.1234567891.21423"
firstNumber = line[:12]
restOfLine = line[12:]
print firstNumber
print restOfLine
Output:
1.012345e007
0.123414e-004-0.1234567891.21423
you can do it like this:
step = 12
for i in range(0, len(string), 12):
slice = string[i:step]
step += 12
in this way on each iteration you will get one slice of 14 characters.
from itertools import izip_longest
def grouper(n, iterable, padvalue=None):
return izip_longest(*[iter(iterable)]*n, fillvalue=padvalue)
I stumbled on this while looking for a solution for a similar problem - but in my case I wanted to split string into chunks of differing lengths. Eventually I solved it with RE
In [13]: import re
In [14]: random_val = '07eb8010e539e2621cb100e4f33a2ff9'
In [15]: dashmap=(8, 4, 4, 4, 12)
In [16]: re.findall(''.join('(\S{{{}}})'.format(l) for l in dashmap), random_val)
Out[16]: [('07eb8010', 'e539', 'e262', '1cb1', '00e4f33a2ff9')]
Bonus
For those who may find it interesting - I tried to create pseudo-random ID by specific rules, so this code is actually part of the following function
import re, time, random
def random_id_from_time_hash(dashmap=(8, 4, 4, 4, 12)):
random_val = ''
while len(random_val) < sum(dashmap):
random_val += '{:016x}'.format(hash(time.time() * random.randint(1, 1000)))
return '-'.join(re.findall(''.join('(\S{{{}}})'.format(l) for l in dashmap), random_val)[0])
I always thought, since string addition operation is possible by a simple logic, may be division should be like this. When divided by a number, it should split by that length. So may be this is what you are looking for.
class MyString:
def __init__(self, string):
self.string = string
def __div__(self, div):
l = []
for i in range(0, len(self.string), div):
l.append(self.string[i:i+div])
return l
>>> m = MyString(s)
>>> m/3
['abc', 'bdb', 'fbf', 'bfb']
>>> m = MyString('abcd')
>>> m/3
['abc', 'd']
If you don't want to create an entirely new class, simply use this function that re-wraps the core of the above code,
>>> def string_divide(string, div):
l = []
for i in range(0, len(string), div):
l.append(string[i:i+div])
return l
>>> string_divide('abcdefghijklmnopqrstuvwxyz', 15)
['abcdefghijklmno', 'pqrstuvwxyz']
Try this function:
x = "1.012345e0070.123414e-004-0.1234567891.21423"
while len(x)>0:
v = x[:12]
print v
x = x[12:]

Categories

Resources