Python - assigning digits of a number to variables [duplicate] - python-3.x

This question already has answers here:
How to split an integer into a list of digits?
(10 answers)
Closed last month.
I'm writing a program which calculates the check digit of an ISBN number. I have to read the user's input (nine digits of an ISBN) into an integer variable, and then multiply the last digit by 2, the second last digit by 3 and so on. How can I "split" the integer into its constituent digits to do this? As this is a basic homework exercise I am not supposed to use a list.

Just create a string out of it.
myinteger = 212345
number_string = str(myinteger)
That's enough. Now you can iterate over it:
for ch in number_string:
print ch # will print each digit in order
Or you can slice it:
print number_string[:2] # first two digits
print number_string[-3:] # last three digits
print number_string[3] # forth digit
Or better, don't convert the user's input to an integer (the user types a string)
isbn = raw_input()
for pos, ch in enumerate(reversed(isbn)):
print "%d * %d is %d" % pos + 2, int(ch), int(ch) * (pos + 2)
For more information read a tutorial.

while number:
digit = number % 10
# do whatever with digit
# remove last digit from number (as integer)
number //= 10
On each iteration of the loop, it removes the last digit from number, assigning it to digit.
It's in reverse, starts from the last digit, finishes with the first

list_of_ints = [int(i) for i in str(ISBN)]
Will give you a ordered list of ints. Of course, given duck typing, you might as well work with str(ISBN).
Edit: As mentioned in the comments, this list isn't sorted in the sense of being ascending or descending, but it does have a defined order (sets, dictionaries, etc in python in theory don't, although in practice the order tends to be fairly reliable). If you want to sort it:
list_of_ints.sort()
is your friend. Note that sort() sorts in place (as in, actually changes the order of the existing list) and doesn't return a new list.

On Older versions of Python...
map(int,str(123))
On New Version 3k
list(map(int,str(123)))

(number/10**x)%10
You can use this in a loop, where number is the full number, x is each iteration of the loop (0,1,2,3,...,n) with n being the stop point. x = 0 gives the ones place, x = 1 gives the tens, x = 2 gives the hundreds, and so on. Keep in mind that this will give the value of the digits from right to left, so this might not be the for an ISBN but it will still isolate each digit.

Convert it to string and map over it with the int() function.
map(int, str(1231231231))

Recursion version:
def int_digits(n):
return [n] if n<10 else int_digits(n/10)+[n%10]

Converting to str is definitely slower then dividing by 10.
map is sligthly slower than list comprehension:
convert to string with map 2.13599181175
convert to string with list comprehension 1.92812991142
modulo, division, recursive 0.948769807816
modulo, division 0.699964046478
These times were returned by the following code on my laptop:
foo = """\
def foo(limit):
return sorted(set(map(sum, map(lambda x: map(int, list(str(x))), map(lambda x: x * 9, range(limit))))))
foo(%i)
"""
bar = """\
def bar(limit):
return sorted(set([sum([int(i) for i in str(n)]) for n in [k *9 for k in range(limit)]]))
bar(%i)
"""
rac = """\
def digits(n):
return [n] if n<10 else digits(n / 10)+[n %% 10]
def rabbit(limit):
return sorted(set([sum(digits(n)) for n in [k *9 for k in range(limit)]]))
rabbit(%i)
"""
rab = """\
def sum_digits(number):
result = 0
while number:
digit = number %% 10
result += digit
number /= 10
return result
def rabbit(limit):
return sorted(set([sum_digits(n) for n in [k *9 for k in range(limit)]]))
rabbit(%i)
"""
import timeit
print "convert to string with map", timeit.timeit(foo % 100, number=10000)
print "convert to string with list comprehension", timeit.timeit(bar % 100, number=10000)
print "modulo, division, recursive", timeit.timeit(rac % 100, number=10000)
print "modulo, division", timeit.timeit(rab % 100, number=10000)

After own diligent searches I found several solutions, where each has advantages and disadvantages. Use the most suitable for your task.
All examples tested with the CPython 3.5 on the operation system GNU/Linux Debian 8.
Using a recursion
Code
def get_digits_from_left_to_right(number, lst=None):
"""Return digits of an integer excluding the sign."""
if lst is None:
lst = list()
number = abs(number)
if number < 10:
lst.append(number)
return tuple(lst)
get_digits_from_left_to_right(number // 10, lst)
lst.append(number % 10)
return tuple(lst)
Demo
In [121]: get_digits_from_left_to_right(-64517643246567536423)
Out[121]: (6, 4, 5, 1, 7, 6, 4, 3, 2, 4, 6, 5, 6, 7, 5, 3, 6, 4, 2, 3)
In [122]: get_digits_from_left_to_right(0)
Out[122]: (0,)
In [123]: get_digits_from_left_to_right(123012312312321312312312)
Out[123]: (1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 1, 3, 1, 2, 3, 1, 2, 3, 1, 2)
Using the function divmod
Code
def get_digits_from_right_to_left(number):
"""Return digits of an integer excluding the sign."""
number = abs(number)
if number < 10:
return (number, )
lst = list()
while number:
number, digit = divmod(number, 10)
lst.insert(0, digit)
return tuple(lst)
Demo
In [125]: get_digits_from_right_to_left(-3245214012321021213)
Out[125]: (3, 2, 4, 5, 2, 1, 4, 0, 1, 2, 3, 2, 1, 0, 2, 1, 2, 1, 3)
In [126]: get_digits_from_right_to_left(0)
Out[126]: (0,)
In [127]: get_digits_from_right_to_left(9999999999999999)
Out[127]: (9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9)
Using a construction tuple(map(int, str(abs(number)))
In [109]: tuple(map(int, str(abs(-123123123))))
Out[109]: (1, 2, 3, 1, 2, 3, 1, 2, 3)
In [110]: tuple(map(int, str(abs(1412421321312))))
Out[110]: (1, 4, 1, 2, 4, 2, 1, 3, 2, 1, 3, 1, 2)
In [111]: tuple(map(int, str(abs(0))))
Out[111]: (0,)
Using the function re.findall
In [112]: tuple(map(int, re.findall(r'\d', str(1321321312))))
Out[112]: (1, 3, 2, 1, 3, 2, 1, 3, 1, 2)
In [113]: tuple(map(int, re.findall(r'\d', str(-1321321312))))
Out[113]: (1, 3, 2, 1, 3, 2, 1, 3, 1, 2)
In [114]: tuple(map(int, re.findall(r'\d', str(0))))
Out[114]: (0,)
Using the module decimal
In [117]: decimal.Decimal(0).as_tuple().digits
Out[117]: (0,)
In [118]: decimal.Decimal(3441120391321).as_tuple().digits
Out[118]: (3, 4, 4, 1, 1, 2, 0, 3, 9, 1, 3, 2, 1)
In [119]: decimal.Decimal(-3441120391321).as_tuple().digits
Out[119]: (3, 4, 4, 1, 1, 2, 0, 3, 9, 1, 3, 2, 1)

Use the body of this loop to do whatever you want to with the digits
for digit in map(int, str(my_number)):

I have made this program and here is the bit of code that actually calculates the check digit in my program
#Get the 10 digit number
number=input("Please enter ISBN number: ")
#Explained below
no11 = (((int(number[0])*11) + (int(number[1])*10) + (int(number[2])*9) + (int(number[3])*8)
+ (int(number[4])*7) + (int(number[5])*6) + (int(number[6])*5) + (int(number[7])*4) +
(int(number[8])*3) + (int(number[9])*2))/11)
#Round to 1 dp
no11 = round(no11, 1)
#explained below
no11 = str(no11).split(".")
#get the remainder and check digit
remainder = no11[1]
no11 = (11 - int(remainder))
#Calculate 11 digit ISBN
print("Correct ISBN number is " + number + str(no11))
Its a long line of code, but it splits the number up, multiplies the digits by the appropriate amount, adds them together and divides them by 11, in one line of code. The .split() function just creates a list (being split at the decimal) so you can take the 2nd item in the list and take that from 11 to find the check digit. This could also be made even more efficient by changing these two lines:
remainder = no11[1]
no11 = (11 - int(remainder))
To this:
no11 = (11 - int(no11[1]))
Hope this helps :)

Similar to this answer but more a more "pythonic" way to iterate over the digis would be:
while number:
# "pop" the rightmost digit
number, digit = divmod(number, 10)

How about a one-liner list of digits...
ldigits = lambda n, l=[]: not n and l or l.insert(0,n%10) or ldigits(n/10,l)

Answer: 165
Method: brute-force! Here is a tiny bit of Python (version 2.7) code to count'em all.
from math import sqrt, floor
is_ps = lambda x: floor(sqrt(x)) ** 2 == x
count = 0
for n in range(1002, 10000, 3):
if n % 11 and is_ps(sum(map(int, str(n)))):
count += 1
print "#%i: %s" % (count, n)

Just assuming you want to get the i-th least significant digit from an integer number x, you can try:
(abs(x)%(10**i))/(10**(i-1))
I hope it helps.

Related

Pair wise permutation of two lists in Python

I have a list with 10 numerical values. I want to return all possible combination of this list such that each element can take value +/- element value.
The approach I had in mind was to take a binary variable which takes in value from 0 to 1023. 1 in this variable corresponds to positive d[i] and 0 to negative d[i].
e.g. for bin(8) = 0000001000 implies that d7 will take value -d7 and rest will be positive. Repeat this for all 0 to 1023 to get all combinations.
For example, if D = [d1,d2,...d10], we will have 1024 (2^10) combinations such that:
D1 = [-d1,d2,d3,....d10]
D2 = [-d1,-d2,d3,....d10]
D3 = [d1,-d2,d3,....d10] ...
D1024 = [-d1,-d1,-d3,....-d10]
Thank You!
you can just use the builtin itertools.product to make all combinations of positive and negative values.
from itertools import product
inputs = list(range(10)) # [1,2,3,4,5,6,7,8,9]
outputs = []
choices = [(x,-x) for x in inputs]
for item in product(*choices):
outputs.append(item)
print(outputs[:3])
print(len(outputs))
# [(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), (0, 1, 2, 3, 4, 5, 6, 7, 8, -9), (0, 1, 2, 3, 4, 5, 6, 7, -8, 9)]
# 1024
in a compressed form:
outputs = [item for item in product(*[(x,-x) for x in inputs])]

Evaluate all possible combinations of values in a set against a specified value

I have a homework problem that requires me to write a function that given an integer k and a list of n unordered integers A, determines if there is a distinct pair of integers in A that sum to k.
I'm struggling to get the function to evaluate all possible combinations of the values in the list. As soon as it gets a pair that does not sum to k it stops. If anyone has any suggestions / tips, I'd greatly appreciate it. I'm not looking for the outright answer, just a nudge in the right direction.
Here is what I have so far:
def sumsToK(k, list1):
newSet = set(list1) #creates set based on list1 to remove any duplicate values
print (newSet)
newSet = list(newSet) #convert back to list so I can iterate through values
for i in range(len(newSet)):
for j in range(i+1, len(newSet)):
print(newSet[i],newSet[j])
if (newSet[i]) + (newSet[j]) == k:
return (print('There is at least one pair if integers that adds up to k'))
else:
return(print('There are is no pair of distinct integers that adds up to k'))
k = 9
list1 = [1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9, 10] #Multiple distinct pairs will sum to 9
print ((sumsToK(k, list1)))
As soon as it gets a pair that does not sum to k it stops
That's normal given your code: you return immediately at the first iteration, whether you did find a pair or did not find a pair.
Remove the second return and you are all set:
def sumsToK(k, list1):
newSet = set(list1) #creates set based on list1 to remove any duplicate values
print (newSet)
newSet = list(newSet) #convert back to list so I can iterate through values
for i in range(len(newSet)):
for j in range(i+1, len(newSet)):
print(newSet[i],newSet[j])
if (newSet[i]) + (newSet[j]) == k:
return('There is at least one pair if integers that adds up to k')
else:
# it's important not to return anything here otherwise you
# exit the loop :)
print('This is not a pair of distinct integers that adds up to k')
k = 9
list1 = [1, 2, 3, 4, 5, 5, 5, 6, 7, 8, 9, 10] #Multiple distinct pairs will sum to 9
print ((sumsToK(k, list1)))
It gives me:
set([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
(1, 2)
(1, 3)
(1, 4)
(1, 5)
(1, 6)
(1, 7)
(1, 8)
There is at least one pair if integers that adds up to k
By the way, do not return print statements, just return the string, or print it (not both!).

Checking whether a list of numbers contains ANY five number sequence

I have a list that only includes positive integers:
my_list = [1, 2, 4, 7, 9, 10, 15, 16]
The list is sorted.
What would be the most "pythonic" way to check whether the list contains any sequence of x consequtive number? It shouldn't matter whether the sequence starts at the beginning of the list, or ends at the end of the list - as long as it's in the list, it should return true. For instance, if I wanted to check if the following list contains a 4-number sequence:
my_list = [1, 3, 4, 5, 6, 8, 10]
It should return true due to [3, 4, 5, 6]
I have seen multiple StackOverflow questions about "finding number sequences in lists", however none of them dealt with looking for a sequence in only a portion of the list. (What I found was useful only if the goal was to check whether the entire list is sequential.)
Here's a one liner:
def has_sequence(L, seq_len):
return any(list(L[i:i+seq_len]) == list(range(L[i],L[i]+seq_len))
for i in range(len(L)-seq_len+1))
def findRun(L, n):
runlen = 0
for i in range(1, len(L)):
if L[i] == L[i-1]+1:
runlen += 1
else:
runlen = 0
if runlen == n-1:
print("Found a run starting at", i-n+1)
Output:
In [451]: L = [1, 3, 4, 5, 6, 8, 10]
In [452]: findRun(L, 4)
Found a run starting at 1
You can try this:
after grouping them with the difference, you just check if any of the groups contains your preferred number of consecutive sequence(in this case 4).
from itertools import groupby
from operator import itemgetter
my_list = [1, 3, 4, 5, 6, 8, 10]
check = False
for key, group in groupby(enumerate(my_list), lambda (i, val): i - val):
g = map(itemgetter(1), group)
if len(g) == 4:
check = True
print(check)
True
I hope this is what you looking for.

Python: Calculate the last digit of a large Fibonacci Number with less time

# Uses python3
# Compute the Last Digit of a Large Fibonacci Number
def Fib_Last_Digit(n):
if n == 0 : return 0
elif n == 1: return 1
else:
a,b = 0,1
for i in range(1,n):
c = a + b;
a = b;
b = c;
# Calculate the last digit of the final number
lastdigit = int(repr(c)[-1]);
print(lastdigit);
n = int(input(""));
Fib_Last_Digit(n);
This code works very well. However, I want to revise the algorithm to save more time and memory. By the way, the input and output should be kept the same with the previous version.
Only keeping the last digit during calculation saves a lot of time:
def fib_last_digit(n):
if n < 2: return n
else:
a, b = 0, 1
for i in range(1,n):
a, b = b, (a+b) % 10
print(b)
n = int(input())
fib_last_digit(n)
Handling numbers that fit in fewer bytes saves time.
When you're working with huge numbers, you can save a lot of time using the answer described here, slightly modified to only keep track of the last digit:
def fib_last_digit(n):
v1, v2, v3 = 1, 1, 0 # initialise a matrix [[1,1],[1,0]]
for rec in bin(n)[3:]: # perform fast exponentiation of the matrix (quickly raise it to the nth power)
calc = (v2*v2) % 10
v1, v2, v3 = (v1*v1+calc) % 10, ((v1+v3)*v2) % 10, (calc+v3*v3) % 10
if rec == '1': v1, v2, v3 = (v1+v2) % 10, v1, v2
return v2
And finally, based on the concept described in Eugene Yarmash's answer (the last digits repeat every 60 steps) we can make an even faster solution (O(1)):
def fib_last_digit(n):
return (
[1, 1, 2, 3, 5, 8, 3, 1, 4, 5, 9, 4, 3, 7, 0, 7, 7, 4, 1, 5, 6, 1, 7, 8, 5, 3, 8, 1, 9, 0, 9, 9, 8, 7, 5, 2, 7, 9, 6, 5, 1, 6, 7, 3, 0, 3, 3, 6, 9, 5, 4, 9, 3, 2, 5, 7, 2, 9, 1, 0]
[n % 60 - 1]
)
The series of final digits of Fibonacci numbers repeats with a cycle length of 60. Therefore, the Nth Fibonacci number has the same last digit as the (N % 60)th, which should be pretty fast to calculate. As an additional optimization, you can keep only the last digit of each term:
def fib_last_digit(n):
a, b = 0, 1
for i in range(n % 60):
a, b = b, (a + b) % 10
return a
print([fib_last_digit(n) for n in range(1, 11)])
Output:
[1, 1, 2, 3, 5, 8, 3, 1, 4, 5]
def fib(n):
phi = (1 + 5 ** 0.5) / 2
fib_n = round(((phi** n) - (phi**-n) )/(5 ** .5))
return fib_n % 10
Phi is your friend.
def fib_digit(n):
f=[1,1]
for i in range(2,n):
f.append((f[i-1]+f[i-2]) % 10 )
return f[-1]
n = int(input())
print(fib_digit(n))
This is one of the simplest answers,i'm sure, there is a faster algorithm.
Here is what I found:
f1, f2 = 0, 1
for i in range(int(input())-1):
f1, f2 = f2, (f1+f2)%10
print(f2)
It took only --- 0.002832174301147461 seconds --- to complete the code.
import time
n = 100000000000000000000000000000000000000000
def printfib(previous, latest, n):
if(latest > n):
return
print(', ', latest, end='')
printfib(latest, previous + latest, n)
start_time = time.time()
print(0, end='')
printfib(0, 1, n)
print(" ")
print("--- %s seconds ---" % (time.time() - start_time))

How to find all numbers in a list that are not part of a pair - using python 3

I am trying to write a python 3 function that finds all numbers in a list (unspecified length) that are not part of a pair.
For example, given the list [1, 2, 1, 3, 2], the function will return 3; and given the list [0, 1, 1, 7, 8, 3, 9, 3, 9], the function will return 0, 7, and 8.
Thanks for your help!
You can use the following function :
>>> def find(l):
... return (i for i in l if l.count(i)==1)
>>> l= [0, 1, 1, 7, 8, 3, 9, 3, 9]
>>> list(find(l))
[0, 7, 8]
This function will return a generator that is contain the elements in list which those count is equal to 1.
I can tell you how I would do it. What does it mean a "pair"?
You should say, find all the numbers repeated oddly in the array.
First plan: (more efficient!)
Sort the list and then a single loop through your list should be enough to find how many numbers of each there are inside and you can generate awhile another list that you will return.
Second plan (nicer in python, but also more expensive because of the number of evaluations though the hole list):
Try the solution of Kasra. 'count' function from 'list' type helps our code but not our efficiency. It counts the number of times that appears the value 'i' on the list 'l', obviously.
If the pair need to be "closed pair" I mean, if you have three 1 (ones), do you have one pair and one single 1? or do you have all the 1 paired? If the second one, the solution of Kasra is Ok. Else you should compare:
if l.count(i) % 2 == 1
This can be easily and efficiently done in 3 lines with collections.Counter.
from collections import Counter
def unpaired(numbers):
for key, count in Counter(numbers).items():
if count % 2:
yield key
print(list(unpaired([1, 2, 1, 3, 2])))
# [3]
print(list(unpaired([0, 1, 1, 7, 8, 3, 9, 3, 9])))
# [0, 7, 8]
My answer comport if you have three equals numbers or if you have one pair and one single number without pair.
def name(array):
o = sorted(array)
c = []
d = []
for i in o:
if o.count(i) % 2 == 1:
c.append(i)
for j in c:
if j not in d:
d.append(j)
return d
or do not use for j in c and use directly:
return list(set(c))
for example:
array = [0, 1, 1, 7, 8, 3, 9, 3, 9, 9]
output: [0, 7, 8, 9]

Resources