python find GCD recursively meet error - python

I have two pieces of python code finding two positive integers' GCD.
Here is the correct one:
def gcdRecur(a, b):
if b == 0:
return a
return gcdRecur(b, a%b)
Here is the one with bug:
def gcdRecur(a, b):
a = max(a, b)
b = min(a, b)
if b == 0:
return a
return gcdRecur(b, a%b)
It's easy to see the differences between these two pieces of code. And I know that there is no need to add
a = max(a, b)
b = min(a, b)
before the control flow. I can't find any logic mistakes in the latter code, but it print out the wrong result.
------use former code find GCD of 182 ans 224------
print out 14
------use former code find GCD of 182 ans 224------
print out 224(wrong answer)
So I guess it may be associated with the principle of recursion in python which I don't know at all. Can anyone help me and tell me what's going on T T.
Thank you.

The problem is when you call a = max(a,b) and b is the max value, the old a will be missing, and a will equal b which leads to gcd(b,b) == b

Related

Trying to sum numbers between numbers more efficiently

TLDR: Need to make code below more efficient.
I'm trying to solve a coding challenge that requires I sum all numbers between two numbers. My code shown below is passing the tests but is taking too long to run, causing me to fail due to a time out.
Is there any way to rewrite this to do the same thing in less time?
EDIT: solved, thank you so much for your solutions
def get_sum(a,b):
res = 0
if b>a:
for i in range(a,b):
res = sum(range(a,b+1))
return res
if a > b:
for i in range (b,a):
res = sum(range(b,a+1))
return res
elif a == b:
return a
a little math won't harm.
so this should work.
def get_sum(a,b):
return (b-a+1)*(a+b)/2
Maybe this?
def get_sum2(a, b):
if a == b:
return a
return sum([n for n in range(a, b+1)] if b > a else [n for n in range(b, a+1)])
if __name__=="__main__":
print(get_sum2(1, 3))
One suggestion, when you find yourself trying to check for the order of parameters do something like this so you don't have to write the same code twice:
if a>b:
a,b = b,a
# your code
Yup. Using the formula for the triangular numbers:
def get_sum(a,b):
if a > b:
b, a = a, b
sum_from_1_to_a = a * (a + 1) / 2
sum_from_1_to_b = b * (b + 1) / 2
return sum_from_1_to_b - sum_from_1_to_a
You can simplify this, obviously, but I left it this way so it is obvious how the formula is being applied.
Also, are you sure if a == b you should return a? Aren't there 0 numbers between them if they have the same value?

LCM calculation code in python outputs wrong value for very hugh inputs

I've written a small piece of code in python to calculate lcm. It works for most of values that are entered manually. however, it fails when I provide the following 2 numbers: 226553150 1023473145 (found with automatic checker)
My code calculates a value of : 46374212988031352
Whereas expected value is : 46374212988031350
I'm not sure what is causing this 1-digit failure. Here is a snippet of my code:
# Uses python3
import sys
a, b = map(int, input().split())
prod = a*b
while b:
a, b = b, a%b
print (int(prod/a))
I've tried printing the prod (product) separately and that looks fine and the value of 'a' (which ultimately should hold the gcd) looks fine too. But in any case, I still keep getting the wrong answer.
When I tried to print the final answer without int, I get the following answer:
4.637421298803135e+16
That looks like a right answer but the formatting is not how I wanted it to be.
Can someone explain what's happening here?
You need to do integer division like:
Code:
prod // a
Why:
The construct:
int(prod / a)
does a floating point division, then converts to an int. This loses some precision.
Test Code:
a, b = 226553150, 1023473145
prod = a * b
while b:
a, b = b, a % b
print(int(prod / a))
print(prod // a)
Results:
46374212988031352
46374212988031350
I've done this recursive code in Python where first it checks the value of second input,if it is zero then it just returns the first input value as GCD else it will have a recursive call to the GCD function.
This code is working for large numbers as well.
Here's the code:
def gcd(a,b):
if(b!=0):
return gcd(b,a%b)
else:
return(a)
a=int(input("Enter val of a= "))
b=int(input("Enter val of b= "))
g=gcd(a,b)
l=(a*b)//g
print("gcd of ",a ,"and", b,"is =",g)
print("lcm of",a, "and", b,"is =",l)
Output Link:
https://i.stack.imgur.com/lJJ3y.png

Check if two values are both non-negative or both negative

Given a pair of integer values, I need to check if both are non-negative or both are negative.
The trivial way is:
def func(a, b):
return (a >= 0 and b >= 0) or (a < 0 and b < 0)
But I am looking for something "neater", which I believe to be possible, so I came up with this:
def func(a, b):
return (a >= 0) ^ (b >= 0) == 0
However, this one feels a little "obscure to the average reader".
Is there a cleaner way?
Multiply them and test against 0:
def func(a, b):
return a * b >= 0
This is Python. We're not about the most concise efficient possible way to do things in all cases - that's for the C++ lads to do.
If (a >= 0 and b >= 0) or (a < 0 and b < 0) is "fast enough", (which would surprise me if not the case), then stick with it. It works, and is VERY obvious what it does.
For either your second solution, or #coldspeed's, I personally would have to write some stuff down on paper to figure out what it's doing, unless the function name was a LOT better than func.

Logical precedence in Python

I have a question about python precedence. I have the following code:
def gcdIter(a, b):
ans = min(a,b)
while ((a%ans is not 0) and (b%ans is not 0)):
ans -= 1
return ans
My question is about the while logical statement. I added several parenthesis just to make sure that the expression would be evaluated the way I was thinking, but is not. The while loop is being breaked before the both expressions are true. Were I'm wrong?
I found a way to do the same thing without using two expressions, in:
def gcdIter(a, b):
ans = min(a,b)
while ((a%ans + b%ans is not 0)) :
ans -= 1
return ans
But I still wanna know why the first code isn't running the way I think it should.
Do not use identity testing (is or is not) to test for numerical equality. Use == or != instead.
while a%ans != 0 and b%ans != 0:
is tests for object identity (that both operators are the same python object), which is not the same thing as testing if the values are equivalent.
Since 0 is also considered False in a boolean context, you can even omit the != in this case:
while a % ans and b % ans:
The fractions module already has a gcd() function that implements the greatest common divisor algorithm correctly:
from fractions import gcd
print gcd(a, b)
It uses the Euclidian algorithm, python style:
def gcd(a, b):
"""Calculate the Greatest Common Divisor of a and b.
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
"""
while b:
a, b = b, a%b
return a

List of numbers whose squares are the sum of two squares

I've just started learning Python and have started doing some problems just to help buid my skills however I am pretty stuck on this question.
Make a list containing all positive integers up to 1000 whose squares can be expressed as a sum of two squares, (i,e., integers p for which p^2=m^2+n^2, where m and n are integers greater than 0.)
Hints: There are several approaches. You might find it helpful to have a list of all the square numbers. The in operator might be useful.
Here's the code that I've come up with so far:
numbers=xrange(1001)
numbers_squared=[x**2 for x in numbers]
a=[]
for x in numbers_squared:
for b in numbers_squared:
if (x+b)**.5 <= 1001:
a.append(x+b)
print a
The problem I get with this is that Python takes years to do these calculations (I've waited about ten minutes and it's still printing numbers). Any hints on how to solve this would be very appreciated.
p.s. The main point is to use lists. Also hints would be more appreciated than the solution itself.
Thank You!
First of all, you aren't solving the problem. You need to do a check to make sure (x+b)**.5 is actually an integer.
Secondly, if you are printing numbers, you have already calculated out all the numbers. Doing the above will decrease the time required for this step.
how about a list comprehension?
calculate for c in range(1,1011)
for b in range (1, c)
for a in range (1, b)
as follows:
x = [(a,b,c) for c in range(1,1001) for b in range(1, c) for a in range(1,b) if a**2+b**2==c**2]
print x
I have timed this and it takes 46 seconds to complete on my computer
This might work:
def isSumOfSquares(n):
"""return True if n can be expressed as the sum of two squares; False otherwise"""
for a in xrange(1,n):
b = n-(a**2)
if b<=0:
return False
elif not math.sqrt(b)%1:
return True
return False
answer = [i for i in xrange(1,1001) if isSumOfSquares(i**2)]
Let me know if this works for you
I just answered this elsewhere!
import math
def is_triple(hypotenuse):
"""return (a, b, c) if Pythagrean Triple, else None"""
if hypotenuse < 4:
return None
c = hypotenuse ** 2
for a in xrange(3, hypotenuse):
b = math.sqrt(c - (a ** 2))
if b == int(b):
return a, int(b), hypotenuse
return None
>>> results = [x for x in range(1001) if is_triple(x)]
>>> len(results)
567
Runs almost instantly.

Categories