When I split certain numbers into "ones" and "tens" in python, like that (98) we code >>>
num = 98
ones = num % 10
tens = num // 10
print(ones) = 8
print(tens) = 9
So, if I have 3 digits number like 321 (based on the code have shown previously) the ones will be 1, tens = 32 . and I need python to execute 3 and 2 separately !!
First, you can use divmod:
tens, ones = divmod(98, 10)
tens
# 9
ones
# 8
Second, you could write a generic function to get all digits regardless of magnitude:
def digs(n):
while n:
n, dig = divmod(n, 10)
yield dig
ones, tens, hundreds, *_ = digs(321)
It will always produce all digits starting with ones:
[*digs(12345)]
# [5, 4, 3, 2, 1]
Of course, the simplest is just string conversion:
[*map(int, str(12345))]
# [1, 2, 3, 4, 5]
This is a generic Python code to split the digits (ones, tens, hundreds, and so on)
num = int(input())
count = 0
while (num != 0):
mod = num % 10
div = num // 10
count = count + 1
print ("The number in position", count, " is ", mod)
num = div
This code works by repeated division.
You can write a function doing the modulo operations, put those in a list, make the division by then and repeat until the end, reverse the list:
def split_number(number):
result = []
while number != 0:
result.append(number % 10)
number = number // 10
result.reverse()
return result
split_number(12345)
[1, 2, 3, 4, 5]
like this :
321 / 100
3.21
>>> int(3.21)
3
But you have already made a better thing for 10 why you don't make it for 100?
Related
How would you go about this:
Write your own infinite precision "sum", "product", and "to the power of" functions, that represent numbers as lists of
digits between 0 and 9 with least significant digit first.
Thus: 0 is represented as the empty list [], and 10 is represented as [0,1].
You may assume that numbers are non-negative (no need for negative numbers, or for subtraction).
I have functions to convert to and from.
eg:
iint(5387) == [7, 8, 3, 5] and pint([7, 8, 3, 5]) == 5387
def iint(n):
# list of all digits in the int
digits = [int(x) for x in str(n)]
# reverse the list
digits.reverse()
return digits
def pint(I):
# new int c
c = 0
# iterates through list
for i in range(len(I)):
# add to c digit in the list multiplied by 10^of its position in the list. 1, 10, 100, 1000 ect.
c = c + I[i] * (10 ** i)
return c
# add two infinite integers
def iadd(I, J):
pass
First though would be just convert back to int do the calculation and then back again but that would "gut the question".
Not looking for a complete solution just some pointers on where to start for iadd()because I am completely stumped. I assume after you get iadd() the rest should be simple enough.
For writing your iadd function, one way is to use test-driven development; write your test inputs, and your expected outputs. assert that they're equal, then rewrite your function so it passes the testcase.
In the particular case of needing to add two lists of numbers together, "how would you do that by hand?" (as noted by a comment) is an excellent place to start. You might
starting from the least-significant digit
add individual digits together (including a carry from the previous digit, if any)
carry the "high" digit if the result is > 9
record the result of that addition
loop from step 2 until you exhaust the shorter number
if you have a carry digit "left over," handle that properly
if one of the input numbers has more digits than the other, properly handle the "left over" digits
Here's a code snippet that should help give some ideas:
for d in range(min(len(I),len(J))):
added = I[d] + J[d]
digit = added%10 + carry
carry = added//10
And some testcases to try:
assert iadd([1], [1]) == [2] # 1 + 1 == 2
assert iadd([0,1], [1]) == [1,1] # 10 + 1 == 11
assert iadd([9,1], [1]) == [0,2] # 19 + 1 == 20
assert iadd([9,9,9,9,9], [2]) == [1,0,0,0,0,1] # 99,999 + 2 == 100,001
assert iadd([4,0,2], [9,2,3,4,1]) == [3,3,5,4,1] # 201 + 14,329 == 14,533
Itertools's zip_longest should be very useful to implement the addition operation.
For example:
def iint(N): return [int(d) for d in reversed(str(N))]
def pint(N): return int("".join(map(str,reversed(N))))
from itertools import zip_longest
def iadd(A,B):
result = [0]
for a,b in zip_longest(A,B,fillvalue=0):
result[-1:] = reversed(divmod(a+b+result[-1],10))
while result and not result[-1]: result.pop(-1) # remove leading zeros
return result
a = iint(1234)
b = iint(8910)
print(iadd(a,b)) # [4, 4, 1, 0, 1] (10144)
For the multiplication, you should make sure to keep the intermediate results below 100
def iprod(A,B):
result = []
for iA,a in enumerate(A):
if not a: continue
result = iadd(result,[0]*iA+[a*d for d in B]) # a*d+9 <= 90
return result
print(iprod(a,b)) # [0, 4, 9, 4, 9, 9, 0, 1] 10994940
For the power operation, you'll want to break down the process into a reasonable number of multiplications. This can be achieved by decomposing the exponent into powers of 2 and multiplying the result by the compounded squares of the base (for 1 bits). But you'll need to make a division by 2 function to implement that.
This strategy is based on the fact that multiplying a base raised to various powers, adds these powers:
A^7 * A^6 = A^13
and that any number can be expressed as the sum of powers of two:
13 = 1 + 4 + 8,
so
A^13 = A^1 * A^4 * A^8.
This reduces the number of multiplications for A^B down to 2log(B) which is much less than multiplying A by itself B-1 times (although we'll be dealing with larger numbers).
def idiv2(N):
result = N.copy() or [0]
carry = 0
for i,d in enumerate(reversed(N),1):
result[-i],carry = divmod(result[-i]+carry*10,2)
return result if result[-1] else result[:-1]
def ipow(A,B):
result, a2n = [1], [] # a2n is compounded squares A, A^2, A^4, A^8, ...
while B:
a2n = iprod(a2n,a2n) if a2n else A
if B[0]%2 : result = iprod(result,a2n)
B = idiv2(B)
return result
print(ipow(iint(12),iint(13)))
# [2, 7, 0, 9, 7, 3, 5, 0, 2, 3, 9, 9, 6, 0, 1] 106993205379072
print(len(ipow(a,b))) # 27544 digits (takes a long time)
Further optimization could be achieved by creating a specialized square function and using it instead of iprod(a2n,a2n)
I would like to generate 4 digits random number in Python but exclude all the numbers that have a "0" inside. For example, 9230, 2012 will not be accepted since there is a 0.
My code is:
def my_custom_random():
exclude=[0]
randInt = randint(1000, 9999)
return my_custom_random() if randInt in exclude else randInt
def Q3a():
RandomNumber = my_custom_random())
print(RandomNumber)
Q3a()
But this code is not working. Anyone can help me ? Thanks.
Congratulations for not picking the easy but expensive solution, consisting in calling 4 times the random number generator for a number between 1 and 9 inclusive.
we can basically keep your recursive scheme, but delegate the hard work to another function, isBadNumber(). Like this:
def my_custom_random():
randInt = random.randint(1111, 9999)
return my_custom_random() if isBadNumber(randInt) else randInt
To decide whether some number is acceptable or not, we need some auxiliary function that returns the list of digits:
# get at least k digits for a number in some arbitrary base:
def xdigits(k, base, n):
if (n < base):
res = (k-1)*[0] + [n]
else:
res = xdigits(k-1, base, n // base) + [n % base]
return res
Trying:
>>>
>>> q.xdigits(4,10,56)
[0, 0, 5, 6]
>>>
>>> q.xdigits(4,10,123456)
[1, 2, 3, 4, 5, 6]
>>>
>>> q.xdigits(4,10,7702)
[7, 7, 0, 2]
>>>
Thus we can write our isBadNumber() function like this:
def isBadNumber(n):
if ((n < 1111) or (n > 9999)):
return True
ds = xdigits(4, 10, n)
if (min(ds) < 1):
return True # having a zero
return False # passed all tests OK.
Addendum: a method without rejection:
Rejection costs CPU time, so it is always nice if we can do without it. For each of the 4 digits, there are 9 possibilities, 1 to 9 inclusive. Hence the overall number of solutions is 94, hence 6561. As programmers use to do, we can decide to number them from 0 to 6560 inclusive.
So we can pick one of them like this:
>>>
>>> import random
>>> import functools as fn
>>>
>>> random.randint(0,6560)
3952
>>>
If we express this number in base 9 (not 10), we get 4 digits between 0 and 8 inclusive. This is exactly what we need, provided we add 1 to every digit.
>>>
>>> q.xdigits(4,9,3952)
[5, 3, 7, 1]
>>>
We add 1 to every digit, giving [6, 4, 8, 2]. Hence, the 3952-th solution is number 6482.
Going from 3952 thru [5,3,7,1] to 6482 can be done using some simple Python data massaging:
>>>
>>> ds1 = list(map(lambda n: n+1, [5, 3, 7, 1]))
>>> ds1
[6, 4, 8, 2]
>>>
>>> fn.reduce(lambda acc, d: acc*10 + d, ds1)
6482
>>>
So overall the rejection-free code would be like this:
def my_custom_random():
randomRank = random.randint(0, 9**4 - 1)
ds0 = xdigits(4, 9, randomRank)
ds1 = list(map(lambda n: n+1, ds0))
num = functools.reduce(lambda acc, d: acc*10 + d, ds1)
return num
Basically, if you don't want zeros then don't pick zeros. Pick from [1..9] only, so you never pick a zero.
Here is some pseudocode; my Python is not good.
function noZeros()
digits <- [1,2,3,4,5,6,7,8,9] // Zero omitted.
result <- 0
repeat 4 times
result <- 10 * result;
thisDigit <- pick a random entry from digits array
result <- result + thisDigit
end repeat
return result
end function noZeros
I am sure you can write a better version in Python.
I hope it will help you
import random
def my_custom_random():
exclude = 0
digits = [0,1,2,3,4,5,6,7,8,9]
randNumber = random.sample(digits,4) #List of integers Ex. [2,9,1,6]
while exclude in randNumber:
randNumber = random.sample(digits,4)
return map(str,randNumber) #map(str, x) -> transform [2,9,1,6] to ['2','9','1','6']
def Q3a():
randNumber = my_custom_random()
randNumber = "".join(randNumber) # ['2','9','1','6'] to '2916'
print(int(randNumber))
Q3a()
In digits you can omit the 0, so you can write less code. This way you will never have numbers with zero.
def my_custom_random():
digits = [1,2,3,4,5,6,7,8,9]
randNumber = random.sample(digits,4)
return map(str,randNumber)
I am working on one of Google's FooBar challenges for fun and running into a Time Limit Exceeded error when executing it in Google's run time environment. My solution runs fine - and to my eyes quickly - in my local development environment.
This is my code:
from itertools import permutations
def answer(l):
options = []
for r in range(1, len(l) + 1):
for p in permutations(l, r=r):
n = int(''.join(map(str, p)))
if n % 3 == 0:
options.append(n)
numbers = sorted(options, reverse=True)
return numbers[0]
l = [3, 1, 4, 1, 5, 9]
#l = [3, 1, 4, 1]
print(answer(l))
The goal is to find the largest number that is divisible by 3 from the list of numbers that is passed in.
The output of the two examples should be:
[3, 1, 4, 1, 5, 9] => 94311
[3, 1, 4, 1] => 4311
Based on the comments to generate the permutations from largest to smallest (instead of smallest to largest) and then breakout, I've modified the code. Against, it works in the local environment but the Google runtime says that the timelimit has been exceeded:
def answer(l):
options = []
l = sorted(l, reverse=True)
for r in range(len(l) + 1, 1, -1):
for p in permutations(l, r=r):
n = int(''.join(map(str, p)))
if n % 3 == 0:
return n
return 0
I am sorting the input list based on the permutations docs that say the tuples will be sorted if the input is sorted. It then, since it should be sorted, the first time it finds a value divisible by 3, that will be the higest value
As I said, my code (both versions) works. But, I seem to be running longer than Google expects. How can I reduce the run time of the above code?
The highest number will have the most number of digits. So for a
list of size n, the search should start from n and continue to n-1,
n-2...
The numbers divisible by 3 will always be in the solution. For
example 2514 is divisible by 3 so is 32514 or 35314. Therefore you can reduce
the search to the digits that are not divisible by 3.
For a list of n digits that are not divisible by 3 (n>=3), you can
get a number divisible by 3 by removing at most 2 digits. This is because the summation will have the remainder 1 or 2. If it is 1, in the worst case you can remove 2 digits with a remainder of 2. If it is 2, again in the worst case you can remove 2 digits with a remainder of 1.
Now the algorithm:
You have a list of numbers:
divisible = [i for i in numbers if i % 3 == 0]
candidate_list = [i for i in numbers if i % 3 != 0]
If the summation of candidate_list is divisible by 3, then you have the answer. If not, look at the remainder:
remainder = sum(candidate_list) % 3
If the remainder is 1, we are going to search for 1, 4, or 7 in the candidate list. If it is 2, the numbers will be 2, 5, and 8. If we find a number, we are going to remove that from the list and the sum of the remaining digits will be divisible by three.
if remainder!=0:
for i in range(3):
if (remainder + i*3) in candidate_list:
candidate_list.remove(remainder + i*3)
return candidate_list
This will start the search from the smallest digit and break out of the loop when a digit is found. If not, we will search for two digits instead of 1.
counter = 0
for candidate in candidate_list:
if candidate % 3 + remainder == 3:
candidate_list.remove(candidate)
counter += 1
if counter > 1:
return candidate_list
Overall, you'll have something like this:
numbers = [3, 1, 4, 1, 5, 9, 0, 2, 4, 7, 9, 1, 3]
divisible = [i for i in numbers if i % 3 == 0]
def search(numbers):
candidate_list = sorted([i for i in numbers if i % 3 != 0])
remainder = sum(candidate_list) % 3
if remainder!=0:
for i in range(3):
if (remainder + i*3) in candidate_list:
candidate_list.remove(remainder + i*3)
return candidate_list
counter = 0
for candidate in candidate_list:
if candidate % 3 + remainder == 3:
candidate_list.remove(candidate)
counter += 1
if counter > 1:
return candidate_list
else:
return candidate_list
candidate_list = search(numbers)
fin = int(''.join(map(str, sorted(divisible + candidate_list, reverse=True))))
I want to know how to add to digits together in a list. Say the number is 10. I need it to add 1 + 0 to the new list. If the item in the list is 11 it needs to add 2 to the list
def main():
#Define List
mylist = [4,5,5,2,7,2,0,4,1,2,3,4,5,6,7,8]
print(mylist)
newlist = []
for each in mylist:
if (each % 2 == 0):
newlist.append(each)
else:
newlist.append(each + each)
for each in newlist:
if each >= 10:
newlist.append(each + each)
print(newlist)
main()
To get the digit sum of a number, you should convert the number to a string, loop over the string, and add all chars together (after converting them to int again):
def get_digit_sum(num):
return sum(int(x) for x in str(num))
To do this for a list of numbers, you should use list comprehension:
>>my_nums = [11, 22, 56, 345]
>>digit_sums = [get_digit_sum(x) for x in my_nums]
>>print(digit_sums)
[2, 4, 11, 12]
This is also possible to do in one expression:
>>my_nums = [11, 22, 56, 345]
>>digit_sums = [sum(int(x) for x in str(num)) for num in my_nums]
As per abarnet's comment, you may want the number 345 to be converted to 3+4+5=12, and the convert 12 to 1+2=3. This can be done using recursion. By using a max_digits parameter, you can specify the maximum number of digits in the returned number.
def get_digit_sum(num, max_digits=1):
d = sum(int(x) for x in str(num))
if len(str(d)) > max_digits:
return get_digit_sum(d)
return d
or a bit shorter:
def get_digit_sum(num, max_digits=1):
d = sum(int(x) for x in str(num))
return get_digit_sum(d) if len(str(d)) > max_digits else d
Both of the above functions would then yield:
>>my_nums = [11, 22, 56, 345]
>>print [get_digit_sum(x) for x in my_nums]
[2, 4, 2, 3]
It looks like your code is trying to do a little bit more than what you describe - in particular, you double any odd numbers. Because you're doing two things to each number (possibly double, sum the digits), you don't want to put it in the list until both steps are done. Instead do something like this:
for each in mylist:
if each % 2 != 0:
each *= 2
if each >= 10:
each = # sum of digits
newlist.append(each)
There's a couple of ways you could sum the digits. You can use divmod to get the quotient and the remainder of the number divided by 10 - the remainder is the units column, the quotient is every column to the left of that:
if each >= 10:
q, r = divmod(each, 10)
each = q + r
the other way is to get the string representation, which lets you iterate over every digit, convert it back to a number and add them:
if each >= 10:
each = sum(int(d) for d in str(each))
this is possibly easier to understand It is, however, a fair bit slower - which might matter if you have a very large amount of input.
These two approaches do work differently if you end up with any three or more digit numbers in the list - for 110, the divmod version will do 11 + 0 = 11, while the string version will do 1 + 1 + 0 = 2.
Also note that neither is guaranteed to end up with a single-digit number in the end - for 99, both of these will give you 18. If you want that further reduced to 9, you can change the if to a loop:
while each >= 10:
each = sum(int(d) for d in str(each))
to do this for the divmod version, you could put it into a recursive function instead:
def digit_sum(number):
q, r = divmod(number, 10)
if q > 10:
q = digit_sum(q)
return q+r
Making the same change to the divmod version as the string version appears to give the same answer in every case I've tried, but I have no idea if this is guaranteed to be the case.
> [int(d) for d in str(123)]
[1, 2, 3]
Try this:
A function that sums the digits for a given number:
def sum_of_digits(num):
return sum([int(x) for x in str(num)])
And a list comprehension to apply it to the entire list:
newlist=[sum_of_digits(number) for number in mylist]
I believe I know what you are going for. If the value is even and less than 10 add it to the new list, if the value is odd then double it and if that is less than 10 add it to the new list. Now if the value is greater than 10 then take the sum of all the digits and add it to the list.
I am sure there is a better way to do this, but this is what I came up with.
list = [4,5,5,2,7,2,0,4,1,2,3,4,5,6,7,8]
newlist = []
for i in list:
if i % 2 == 0 and len(str(i)) > 1:
newlist.append(sum([int(x) for x in str(i)]))
elif i % 2 == 0:
newlist.append(i)
elif len(str(i*2)) > 1:
newlist.append(sum([int(x) for x in str(i*2)]))
else:
newlist.append(i*2)
print newlist
input: [4, 5, 5, 2, 7, 2, 0, 4, 1, 2, 3, 4, 5, 6, 7, 8]
outcome: [4, 1, 1, 2, 5, 2, 0, 4, 2, 2, 6, 4, 1, 6, 5, 8]
I want to divide number into digits and save them in list (or array) in python. So firstly I should create list like
dig = [0 for i in range(10)]
and then
i = 0
while num > 9:
dig[i] = num % 10
i += 1
num /= 10
dig[i] = num
But I don't really like just creating list for 10 spaces, is it possible to get length of number without repeating loop
i = 0
num2 = num
while num2 > 9:
num2 /= 10
i += 1
i += 1
and then repeat first part of code? Or just make as I made in first place? I don't know exact length of number but it won't be very long
So any advices? Maybe you know better way to divide numbers into digits, or maybe something else.
Since you're just adding the digits from smallest to greatest in order, just use an empty list:
dig = []
i = 0
while num > 9:
dig.append(num % 10)
i += 1
num /= 10
dig.append(num)
Alternatively, just do
dig = list(int(d) for d in str(num))
Which will turn i.e. 123 into '123' then turn each digit back into a number and put them into a list, resulting in [1, 2, 3].
If you want it in the same order as your version, use
dig = reversed(int(d) for d in str(num))
If you really just want to get the length of a number, it's easiest to do len(str(num)) which turns it into a string then gets the length.
Assuming num is a positive integer, the number of digits is equal to int(math.log10(num) + 1).
But better than that is to just use the append method of list -- then you won't have to know the length beforehand.
Even easier (though the list will be in reverse order):
dig = [int(x) for x in str(num)]
or
dig = map(int, str(num))
Although map is often said to be unpythonic, this task is definitely for it:
>>> d = 123456
>>> map(int, str(d))
[1, 2, 3, 4, 5, 6]