Long multiplication of two numbers given as strings - python

I am trying to solve a problem of multiplication. I know that Python supports very large numbers and it can be done but what I want to do is
Enter 2 numbers as strings.
Multiply those two numbers in the same manner as we used to do in school.
Basic idea is to convert the code given in the link below to Python code but I am not very good at C++/Java. What I want to do is to understand the code given in the link below and apply it for Python.
https://www.geeksforgeeks.org/multiply-large-numbers-represented-as-strings/
I am stuck at the addition point.
I want to do it it like in the image given below
So I have made a list which stores the values of ith digit of first number to jth digit of second. Please help me to solve the addition part.
def mul(upper_no,lower_no):
upper_len=len(upper_no)
lower_len=len(lower_no)
list_to_add=[] #saves numbers in queue to add in the end
for lower_digit in range(lower_len-1,-1,-1):
q='' #A queue to store step by step multiplication of numbers
carry=0
for upper_digit in range(upper_len-1,-1,-1):
num2=int(lower_no[lower_digit])
num1=int(upper_no[upper_digit])
print(num2,num1)
x=(num2*num1)+carry
if upper_digit==0:
q=str(x)+q
else:
if x>9:
q=str(x%10)+q
carry=x//10
else:
q=str(x%10)+q
carry=0
num=x%10
print(q)
list_to_add.append(int(''.join(q)))
print(list_to_add)
mul('234','567')
I have [1638,1404,1170] as a result for the function call mul('234','567') I am supposed to add these numbers but stuck because these numbers have to be shifted for each list. for example 1638 is supposed to be added as 16380 + 1404 with 6 aligning with 4, 3 with 0 and 8 with 4 and so on. Like:
1638
1404x
1170xx
--------
132678
--------

I think this might help. I've added a place variable to keep track of what power of 10 each intermediate value should be multiplied by, and used the itertools.accumulate function to produce the intermediate accumulated sums that doing so produces (and you want to show).
Note I have also reformatted your code so it closely follows PEP 8 - Style Guide for Python Code in an effort to make it more readable.
from itertools import accumulate
import operator
def mul(upper_no, lower_no):
upper_len = len(upper_no)
lower_len = len(lower_no)
list_to_add = [] # Saves numbers in queue to add in the end
place = 0
for lower_digit in range(lower_len-1, -1, -1):
q = '' # A queue to store step by step multiplication of numbers
carry = 0
for upper_digit in range(upper_len-1, -1, -1):
num2 = int(lower_no[lower_digit])
num1 = int(upper_no[upper_digit])
print(num2, num1)
x = (num2*num1) + carry
if upper_digit == 0:
q = str(x) + q
else:
if x>9:
q = str(x%10) + q
carry = x//10
else:
q = str(x%10) + q
carry = 0
num = x%10
print(q)
list_to_add.append(int(''.join(q)) * (10**place))
place += 1
print(list_to_add)
print(list(accumulate(list_to_add, operator.add)))
mul('234', '567')
Output:
7 4
7 3
7 2
1638
6 4
6 3
6 2
1404
5 4
5 3
5 2
1170
[1638, 14040, 117000]
[1638, 15678, 132678]

Related

PYTHON - "Love for Mathematics"

I just finished a challenge on Dcoder ("Love for Mathematics") using Python. I failed two test-cases, but got one right. I used somewhat of a lower level of Python for the same as I haven't explored more yet, so I'm sorry if it looks a bit too basic.The Challenge reads:
Students of Dcoder school love Mathematics. They love to read a variety of Mathematics books. To make sure they remain happy, their Mathematics teacher decided to get more books for them.
A student would become happy if there are at least X Mathematics books in the class and not more than Y books because they know "All work and no play makes Jack a dull boy".The teacher wants to buy a minimum number of books to make the maximum number of students happy.
The Input
The first line of input contains an integer N indicating the number of students in the class. This is followed up by N lines where every line contains two integers X and Y respectively.
#Sample Input
5
3 6
1 6
7 11
2 15
5 8
The Output
Output two space-separated integers that denote the minimum number of mathematics books required and the maximum number of happy students.
Explanation: The teacher could buy 5 books and keep student 1, 2, 4 and 5 happy.
#Sample Output
5 4
Constraints:
1 <= N <= 10000
1 <= X, Y <= 10^9
My code:
n = int(input())
l = []
mi = []
ma = []
for i in range(n):
x, y = input().split()
mi.append(int(x))
ma.append(int(y))
if i == 0:
h=ma[0]
else:
if ma[i]>h:
h=ma[i]
for i in range(h):
c = 0
for j in range(len(mi)):
if ma[j]>=i and mi[j]<=i:
c+=1
l.append(c)
great = max(l)
for i in range(1,len(l)+1):
if l[i]==great:
print(i,l[i])
break
My Approach:
I first assigned the two minimum and maximum variables to two different lists - one containing the minimum values, and the other, the maximum. Then I created a loop that processes all numbers from 0 to the maximum possible value of the list containing maximum values and increasing the count for each no. by 1 every time it lies within the favorable range of students.
In this specific case, I got that count list to be (for the above given input):
[1,2,3,3,4,4,3,3,2 ...] and so on. So I could finalize that 4 would be the maximum no. of students and that the first index of 4 in the list would be the minimum no. of textbooks required.
But only 1 test-case worked and two failed. I would really appreciate it if anyone could help me out here.
Thank You.
This problem is alike minimum platform problem.
In that, you need to sort the min and max maths books array in ascending order respectively. Try to understand the problem from the above link (platform problem) then this will be a piece of cake.
Here is your solution:
n = int(input())
min_books = []
max_books = []
for i in range(n):
x, y = input().split()
min_books.append(int(x))
max_books.append(int(y))
min_books.sort()
max_books.sort()
happy_st_result = 1
happy_st = 1
books_needed = min_books[0]
i = 1
j = 0
while (i < n and j < n):
if (min_books[i] <= max_books[j]):
happy_st+= 1
i+= 1
elif (min_books[i] > max_books[j]):
happy_st-= 1
j+= 1
if happy_st > happy_st_result:
happy_st_result = happy_st
books_needed = min_books[i-1]
print(books_needed, happy_st_result)
Try this, and let me know if you need any clarification.
#Vinay Gupta's logic and explanation is correct. If you think on those lines, the answer should become immediately clear to you.
I have implemented the same logic in my code below, except using fewer lines and cool in-built python functions.
# python 3.7.1
import itertools
d = {}
for _ in range(int(input())):
x, y = map(int, input().strip().split())
d.setdefault(x, [0, 0])[0] += 1
d.setdefault(y, [0, 0])[1] += 1
a = list(sorted(d.items(), key=lambda x: x[0]))
vals = list(itertools.accumulate(list(map(lambda x: x[1][0] - x[1][1], a))))
print(a[vals.index(max(vals))][0], max(vals))
The above answer got accepted in Dcoder too.

find if a number divisible by the input numbers

Given two numbers a and b, we have to find the nth number which is divisible by a or b.
The format looks like below:
Input :
First line consists of an integer T, denoting the number of test cases.
Second line contains three integers a, b and N
Output :
For each test case, print the Nth
number in a new line.
Constraints :
1≤t≤105
1≤a,b≤104
1≤N≤10
Sample Input
1
2 3 10
Sample Output
15
Explanation
The numbers which are divisible by 2
or 3 are: 2,3,4,6,8,9,10,12,14,15 and the 10th number is 15
My code
test_case=input()
if int(test_case)<=100000 and int(test_case)>=1:
for p in range(int(test_case)):
count=1
j=1
inp=list(map(int,input().strip('').split()))
if inp[0]<=10000 and inp[0]>=1 and inp[1]<=10000 and inp[1]>=1 and inp[1]<=1000000000 and inp[1]>=1:
while(True ):
if count<=inp[2] :
k=j
if j%inp[0]==0 or j%inp[1] ==0:
count=count+1
j=j+1
else :
j=j+1
else:
break
print(k)
else:
break
Problem Statement:
For single test case input 2000 3000 100000 it is taking more than one second to complete.I want if i can get the results in less than 1 second. Is there a time efficient approach to this problem,may be if we can use some data structure and algorithms here??
For every two numbers there will be number k such that k=a*b. There will only be so many multiples of a and b under k. This set can be created like so:
s = set(a*1, b*1, ... a*(b-1), b*(a-1), a*b)
Say we take the values a=2, b=3 then s = (2,3,4,6). These are the possible values of c:
[1 - 4] => (2,3,4,6)
[5 - 8] => 6 + (2,3,4,6)
[9 - 12] => 6*2 + (2,3,4,6)
...
Notice that the values repeat with a predictable pattern. To get the row you can take the value of c and divide by length of the set s (call it n). The set index is the mod of c by n. Subtract 1 for 1 indexing used in the problem.
row = floor((c-1)/n)
column = `(c-1) % n`
result = (a*b)*row + s(column)
Python impl:
a = 2000
b = 3000
c = 100000
s = list(set([a*i for i in range(1, b+1)] + [b*i for i in range(1, a+1)]))
print((((c-1)//len(s)) * (a*b)) + s[(c - 1)%len(s)])
I'm not certain to grasp exactly what you're trying to accomplish. But if I get it right, isn't the answer simply b*(N/2)? since you are listing the multiples of both numbers the Nth will always be the second you list times N/2.
In your initial example that would be 3*10/2=15.
In the code example, it would be 3000*100000/2=150'000'000
Update:
Code to compute the desired values using set's and lists to speed up the calculation process. I'm still wondering what the recurrence for the odd indexes could be if anyone happens to stumble upon it...
a = 2000
b = 3000
c = 100000
a_list = [a*x for x in range(1, c)]
b_list = [b*x for x in range(1, c)]
nums = set(a_list)
nums.update(b_list)
nums = sorted(nums)
print(nums[c-1])
This code runs in 0.14s on my laptop. Which is significantly below the requested threshold. Nonetheless, this values will depend on the machine the code is run on.

While Loop to produce Mathematical Sequences?

I've been asked to do the following:
Using a while loop, you will write a program which will produce the following mathematical sequence:
1 * 9 + 2 = 11(you will compute this number)
12 * 9 + 3 = 111
123 * 9 + 4 = 1111
Then your program should run as far as the results contain only "1"s. You can build your numbers as string, then convert to ints before calculation. Then you can convert the result back to a string to see if it contains all "1"s.
Sample Output:
1 * 9 + 2 = 11
12 * 9 + 3 = 111
123 * 9 + 4 = 1111
1234 * 9 + 5 = 11111
Here is my code:
def main():
Current = 1
Next = 2
Addition = 2
output = funcCalculation(Current, Addition)
while (verifyAllOnes(output) == True):
print(output)
#string concat to get new current number
Current = int(str(Current) + str(Next))
Addition += 1
Next += 1
output = funcCalculation(Current, Next)
def funcCalculation(a,b):
return (a * 9 + b)
def verifyAllOnes(val):
Num_str = str(val)
for ch in Num_str:
if(str(ch)!= "1"):
return False
return True
main()
The bug is that the formula isn't printing next to the series of ones on each line. What am I doing wrong?
Pseudo-code:
a = 1
b = 2
result = a * 9 + b
while string representation of result contains only 1s:
a = concat a with the old value of b, as a number
b = b + 1
result = a * 9 + b
This can be literally converted into Python code.
Testing all ones
Well, for starters, here is one easy way to check that the value is all ones:
def only_ones(n):
n_str = str(n)
return set(n_str) == set(['1'])
You could do something more "mathy", but I'm not sure that it would be any faster. It would much more easily
generalize to other bases (than 10) if that's something you were interested in though
def only_ones(n):
return (n % 10 == 1) and (n == 1 or only_ones2(n / 10))
Uncertainty about how to generate the specific recurrence relation...
As for actually solving the problem though, it's actually not clear what the sequence should be.
What comes next?
123456
1234567
12345678
123456789
?
Is it 1234567890? Or 12345678910? Or 1234567900?
Without answering this, it's not possible to solve the problem in any general way (unless in fact the 111..s
terminate before you get to this issue).
I'm going to go with the most mathematically appealing assumption, which is that the value in question is the
sum of all the 11111... values before it (note that 12 = 11 + 1, 123 = 111 + 11 + 1, 1234 = 1111 + 111 + 11 + 1, etc...).
A solution
In this case, you could do something along these lines:
def sequence_gen():
a = 1
b = 1
i = 2
while only_ones(b):
yield b
b = a*9 + i
a += b
i += 1
Notice that I've put this in a generator in order to make it easier to only grab as many results from this
sequence as you actually want. It's entirely possible that this is an infinite sequence, so actually running
the while code by itself might take a while ;-)
s = sequence_gen()
s.next() #=> 1
s.next() #=> 11
A generator gives you a lot of flexibility for things like this. For instance, you could grab the first 10 values of the sequence using the itertools.islice
function:
import itertools as it
s = sequence_gen()
xs = [x for x in it.islice(s, 10)]
print xs

Python iterating - problems finding the product of digits in a string

Trying to iterate through a number string in python and print the product of the first 5 numbers,then the second 5, then the third 5, etc etc. Unfortunately, I just keep getting the product of the first five digits over and over. Eventually I'll append them to a list. Why is my code stuck?
edit: Original number is an integer so I have to make it a string
def product_of_digits(number):
d= str(number)
for integer in d:
s = 0
k = []
while s < (len(d)):
print (int(d[s])*int(d[s+1])*int(d[s+2])*int(d[s+3])*int(d[s+4]))
s += 1
print (product_of_digits(a))
Let me list out the mistakes in the program.
You are iterating over d for nothing. You don't need that.
s += 1 is not part of the while loop. So, s will never get incremented, leading to infinite loop.
print (product_of_digits(a)) is inside the function itself, where a is not defined.
To find the product of all the consecutive 5 numbers, you cannot loop till the end of d. So, the loop should have been while s <= (len(d)-5):
You have initialized k, but used it nowhere.
So, the corrected program looks like this
def product_of_digits(number):
d, s = str(number), 0
while s <= (len(d)-5):
print(int(d[s]) * int(d[s+1]) * int(d[s+2]) * int(d[s+3]) * int(d[s+4]))
s += 1
product_of_digits(123456)
Output
120
720
You can also use a for loop, like this
def product_of_digits(number):
d = str(number)
for s in range(len(d) - 4):
print(int(d[s]) * int(d[s+1]) * int(d[s+2]) * int(d[s+3]) * int(d[s+4]))
There are a few problems with your code:
1) Your s+=1 indentation is incorrect
2) It should be s+=5 instead (assuming you want products of 1-5, 6-10, 11-15 and so on otherwise s+=1 is fine)
def product_of_digits(number):
d = str(number)
s = 0
while s < (len(d)-5):
print (int(d[s])*int(d[s+1])*int(d[s+2])*int(d[s+3])*int(d[s+4]))
s += 5 (see point 2)
print (product_of_digits(124345565534))
numpy.product([int(i) for i in str(s)])
where s is the number.

Sum of Digits, properties, hint please

This is the problem:
How many integers 0 ≤ n < 10^18 have the property that the sum of the digits of n equals the sum of digits of 137n?
This solution is grossly inefficient. What am I missing?
#!/usr/bin/env python
#coding: utf-8
import time
from timestrings import *
start = time.clock()
maxpower = 18
count = 0
for i in range(0, 10 ** maxpower - 1):
if i % 9 == 0:
result1 = list(str(i))
result2 = list(str(137 * i))
sum1 = 0
for j in result1:
sum1 += int(j)
sum2 = 0
for j in result2:
sum2 += int(j)
if sum1 == sum2:
print (i, sum1)
count += 1
finish = time.clock()
print ("Project Euler, Project 290")
print ()
print ("Answer:", count)
print ("Time:", stringifytime(finish - start))
First of all, you are to count, not to show the hits.
That is very important. All you have to do is to device an efficient way to count it. Like Jon Bentley wrote in Programming Pearls: "Any methond that considers all permutations of letters for a word is doomed to failure". In fact, I tried in python, as soon as "i" hit 10^9, the system already freezed. 1.5 G memory was consumed. Let alone 10^18. And this also tells us, cite Bentley again, "Defining the problem was about ninety percent of this battle."
And to solve this problem, I can't see a way without dynamic programming (dp). In fact, most of those ridiculously huge Euler problems all require some sort of dp. The theory of dp itself is rather academic and dry, but to implement the idea of dp to solve real problems is not, in fact, the practice is fun and colorful.
One solution to the problem is, we go from 0-9 then 10-99 then 100-999 and so on and extract the signatures of the numbers, summarize numbers with the same signature and deal with all of them as a piece, thus save space and time.
Observation:
3 * 137 = 411 and 13 * 137 = 1781. Let's break the the first result "411" down into two parts: the first two digits "41" and the last digit "1". The "1" is staying, but the "41" part is going to be "carried" to further calculations. Let's call "41" the carry, the first element of the signature. The "1" will stay as the rightest digit as we go on calculating 13 * 137, 23 * 137, 33 * 137 or 43 * 137. All these *3 numbers have a "3" as their rightest digit and the last digit of 137*n is always 1. That is, the difference between this "3" and "1" is +2, call this +2 the "diff" as the second element of the signature.
OK, if we are gonna find a two-digit number with 3 as its last digit, we have to find a digit "m" that satisfies
diff_of_digitsum (m, 137*m+carry) = -2 (1)
to neutralize our +2 diff accumulated earlier. If m could do that, then you know m * 10 + 3, on the paper you write: "m3", is a hit.
For example, in our case we tried digit 1. diff_of_digitsum (digit, 137*digit+carry) = diff_of_digitsum (1, 137*1+41) = -15. Which is not -2, so 13 is not a hit.
Let's see 99. 9 * 137 = 1233. The "diff" is 9 - 3 = +6. "Carry" is 123. In the second iteration when we try to add a digit 9 to 9 and make it 99, we have diff_of_digitsum (digit, 137*digit+carry) = diff_of_digitsum (9, 137*9+123) = diff_of_digitsum (9, 1356) = -6 and it neutralizes our surplus 6. So 99 is a hit!
In code, we just need 18 iteration. In the first round, we deal with the single digit numbers, 2nd round the 2-digit numbers, then 3-digit ... until we get to 18-digit numbers. Make a table before the iterations that with a structure like this:
table[(diff, carry)] = amount_of_numbers_with_the_same_diff_and_carry
Then the iteration begins, you need to keep updating the table as you go. Add new entries if you encounter a new signature, and always update amount_of_numbers_with_the_same_diff_and_carry. First round, the single digits, populate the table:
0: 0 * 137 = 0, diff: 0; carry: 0. table[(0, 0)] = 1
1: 1 * 137 = 137. diff: 1 - 7 = -6; carry: 13. table[(-6, 13)] = 1
2: 2 * 137 = 274. diff: 2 - 7 = -5; carry: 27. table[(-5, 27)] = 1
And so on.
Second iteration, the "10"th digit, we will go over the digit 0-9 as your "m" and use it in (1) to see if it can produce a result that neutralizes the "diff". If yes, it means this m is going to make all those amount_of_numbers_with_the_same_diff_and_carry into hits. Hence counting not showing. And then we can calculate the new diff and carry with this digit added, like in the example 9 has diff 6 and carry 123 but 99 has the diff 9 - 6 ( last digit from 1356) = 3 and carry 135, replace the old table using the new info.
Last comment, be careful the digit 0. It will appear a lot of times in the iteration and don't over count it because 0009 = 009 = 09 = 9. If you use c++, make sure the sum is in unsigned long long and that sort because it is big. Good luck.
You are trying to solve a Project Euler problem by brute force. That may work for the first few problems, but for most problems you need think of a more sophisticated approach.
Since it is IMHO not OK to give advice specific to this problem, take a look at the general advice in this answer.
This brute force Python solution of 7 digits ran for 19 seconds for me:
print sum(sum(map(int, str(n))) == sum(map(int, str(137 * n)))
for n in xrange(0, 10 ** 7, 9))
On the same machine, single core, same Python interpreter, same code, would take about 3170 years to compute for 18 digits (as the problem asked).
See dgg32's answer for an inspiration of a faster counting.

Categories