How this greatest common divisor (gcd) works in python - python

I have taken a piece of code from http://www.s-anand.net/euler.html, problem 5:
def gcd(a,b):
print a,b
return b and gcd(b, a % b) or a
print gcd(10,20)
Giving output:
10 20
20 10
10 0
10
Why the last line prints only "a" not b.
Can you please explain how the return statement in above code works.
I am little bit confused with "and" and "or" operators.

b and gcd(b, a % b) or a
was the old way of writing:
gcd(b, a % b) if b else a

Python's and and or operators use a type of short-circut evaluation that is a little confusing at first.
If they were written as function, they would work sort-of like this, except that they don't even evaluate the right value unless they need to.
def and(left, right):
if left:
return right
else:
return left
def or(left, right):
if left:
return left
else:
return right
So the line return b and gcd(b, a % b) or a could be written more verbosely as:
if b:
temp_1 = gcd(b, a % b)
else:
temp_1 = False
if temp_1:
return temp_1
else:
return a
If you work out the logic, this is equivalent to the common method for finding a GCD. However, unless you're already familiar with Python this code will be hard to read, so you might want to avoid this style.

Because 10 is the greatest common divisor in your case, e.g. result of gcd(10,20)
Your code(return b and gcd(...) or a) is the same as:
def gcd(a,b):
print a,b
if b:
return b
else:
res = gcd(b, a % b)
return res if res else a
Also note that there gcd method in fractions module:
from fractions import gcd
print gcd(10,20)

Related

Unable to return in if block while calculating GCD [duplicate]

This question already has answers here:
Python recursive function returning none after completion
(3 answers)
Closed 4 years ago.
I am trying to calculate a GCD of 2 numbers, the following code block works fine, I am using recursion, but when I am trying to return a value I am not able to do so, return a results in None
def gcd(a,b):
if b == 0:
print a
return a # This is not working
else:
gcd(b,a%b)
XX = gcd(3, 5)
print (XX)
Output:
1
None
Your code
def gcd(a,b):
if b == 0:
print a
return a # This is not working
else:
gcd(b,a%b)
XX=gcd(3,5)
print (XX)
will not work, because you are missing the return statement in the line gcd(b,a%b). So it should be
def gcd(a,b):
if b == 0:
print a
return a
else:
return gcd(b,a%b)
print(gcd(12, 4))
By the way - if possible, don't code things yourself, use the predefined library:
from fractions import gcd
print(gcd(4, 12))
Your recursion will not work... you are missing a return statement and also the algorithm does not work...
This is what a recursive gcd could look like:
def gcd(a,b):
r = a % b
if r == 0:
return a
elif r == 1:
return 1
return gcd(b, r)
and here a non-recursive gcd:
def gcd(a, b):
while b:
a, b = b, a % b
return a
also note that you could just use math.gcd.

Function would not return value, instead it returns "None"

Please help me look at this piece of code which was supposed to calculate the greatest common division between two numbers (a, b). The problem I'm having is that the program would not return c as expected, instead it return None. But when I use a print statement, it prints out the value of c.
This is my code:
def gcd(a, b):
if a == 0:
return b
elif b == 0:
return a
elif a > b:
big, small = a, b
else:
big, small = b, a
c = big % small
if c == 0:
print(small)
return small
gcd(small, c)
print(gcd(1071, 462))
Thanks guys.
Python implicitly returns None when no explicit return is encountered and the function body ends.
In your case if it passes through all other cases it just hits:
gcd(small, c)
return None # you haven't put that in explicitly but that's how Python processes it
So you probably just need to change the last line to:
return gcd(small, c)

Maximum recursion, GCD(greatest common divisor)

I wrote a program to find gcd using python.
def gcd(a,b):
r=a%b
if r==0:
return a
elif r==1:
return 1
else:
gcd(a,b)==gcd(b,r)
return gcd(b,r)
Whenever I call the function it shows the message "Max. recursion exceeded." Please help
I know it can be done using looping but I want to specifically do it by using recursion method. And bear with me. I am a learner!
This statement is unnecessary and it's the one making the recursion endless: gcd(a,b)==gcd(b,r) because it's calling gcd(a,b) again and again. Just remove it:
def gcd(a,b):
r=a%b
if r==0:
return a
elif r==1:
return 1
return gcd(b,r)
Note: By the way, you got the formula wrong, you should return b on the if clause since you're dividing a/b when calculating the modulo.
def gcd(a,b):
r=a%b
if r==0:
return b
elif r==1:
return 1
return gcd(b,r)
>>>gcd(10,4)
2
If you're trying to calculate the GCD of very large numbers (e.g., when searching for common factors in RSA moduli), you might be better off avoiding recursion altogether and using an iterative function instead. For example:
def gcd(a,b):
while a:
a,b = b%a,a
return b
gcd(a,b)==gcd(b,r) doesn't do what you expect it to do.
It doesn't mean "define gcd(a,b) to be equal to gcd(b,r)".
Instead, gcd(a,b)==gcd(b,r) means:
Compute gcd(a,b)
Compute gcd(b,r)
Compare the two results and see if they're equal.
Since you're asking to compute gcd(a, b) in order to compute gcd(a, b), you'll get an endless recursion.
Instead, you want the return gcd(b, r) at that point. I.e.:
def gcd(a,b):
r=a%b
if r==0:
return a
elif r==1:
return 1
else:
return gcd(b,r)
This is how I did it
def gcd(m,n):
if m >= n:
r = m % n
if r == 0:
return n
else:
m = n
n = r
return gcd(m,n)
else:
temp = m
m = n
n = temp
return gcd(m,n)
def gcd(a,b):
if a % b == 0:
return b
return gcd(b, a % b)

Finding out whether a is a power of b

I'm currently using singpath.com to practice on my python, but I face an issue with a problem:
A number, a, is a power of b if it is divisible by b and a/b is a power of b.
Write a function called is_power that takes parameters a and b and returns True if a is a power of b.
def is_power(a,b):
c = a/b
if (((a%b) == 0) and ((c%b) == 0)):
return True
else:
return False
Above is my solution but the system prompt me to generalize my solution.
Can anyone tell me whats wrong with my solution?
The reason why your original code does not work is the following: You just check (c%b) == 0) aka (a/b) is divisible by b, which is much weaker than the a/b is a power of b part of the definition.
When you want to solve a problem such as this you should always start with the trivial cases. In this case there are two such cases: is_power(x,x) and is_power(1,x) - in both the answer is True, because x**1==x and x**0==1.
Once you have these cases covered you just need to write down the rest of the definition. Write code for (a is divisible by b) and (a/b is a power of b) and put it all together.
The final function will look like this:
def is_power(a,b):
if <trivial case 1> or <trivial case 2>:
return True
# its a recursive definition so you have to use `is_power` here
return <a is divisible by b> and <a/b is a power of b>
The only question left is how to answer <a/b is a power of b>. The easiest way to do this is using the function is_power itself - this is called recursion.
def is_power(a,b):
'''this program checks if number1 is a power of number2'''
if (a<b): # lesser number isn't a power of a greater number
return False
elif (b==0) or (b==1) : # Exception cases
return False
elif a%b == 0 and is_power(a/b, b) == True: # Condition check for is_power (Recursion!)
return True
else:
return False
You are only checking the first two powers: a divides b and a/b divides b. It could be that a = b ** 3 or b ** 4 (or b ** n in general), so the actual solution will have to involve recursion or a loop.
Here is my solution.
def is_power(a,b):
if a == 1: # base case for recursion
return True
elif b == 0 or a%b !=0 or a<b: # exception cases.
return False
return is_power(a//b,b) # recursion
I tested with several cases (16,2),(6,2),(1,2),(0,0),(0,1) and it works well.
A much simpler solution is:
def is_power(a, b):
while a % b == 0:
a //= b
return a == 1
Recursion is really not needed for this problem. Moreover recusion may cause a recursion limit error if a = b ** 1001.
def is_power(a,b):
if a == b:
return True
if a % b == 0 and is_power(a/b,b):
return True
return False
The end condition which is a == b is crucial here which stops when both numbers are equal. If this is not included the function could show False for even legitimate numbers by dividing a/b in the next iteration which gives 1 where 1 % b = 1 which in turn returns False instead of True.
I wouldn't say to generalize it. I would say to correct it as it's incorrect. Using your solution is_power(12,2) returns True as does is_power(18,3).
I think that the reason that the system says to generalize it is that it's probably working correctly for some of their test cases, but not others. It's likely that the test cases for which it is working are coincidentally those for which it would work if it were hard-coded in a certain way (only checking powers of 2, for example).
You're checking whether a/b is divisible by b (in the expression (c%b) == 0), rather than whether a/b is a power of b. Hint: What function would you call to see whether something is a power of b?
To understand recursion, you need first to understand recursion.
def is_power(a, b):
if a < b: # 3 is never a power of 10, right?
return False # prevent recursion
if a == b: # a is always a**1, right?
return True # prevent recursion
else:
return is_power(a / b, b) # recursion!
Note that for integers a / b will give you rounding errors. Make sure you pass floats.
I don't think you have the right implementation. Based on the problem, the is_power function should look something like this:
def is_power(a,b):
if a%b == 0 and is_power(float(a)/float(b), b):
return True
else:
return False
You are answering to the first constraint but not to the second,
You check to see that (a/b)%b == 0 which is a special case of "(a/b) is a power of b".
Therefor the generalization error (try to think of generalizing that specific case.
What you wrote is not a solution to is power of for example you will indicate 12 as a power of 2 since:
12%2 = 0,
(12/2)%2 = 0
But that is clearly wrong.
As others said, think of recursion (or the less preferable looping solution).
I was just working on this question myself, and this is what I came up with.
To write this as a recursive function, you need the recursive part and the trivial part. For the recursive part, a number is the power of another number if:
((a%b)==0) and (is_power(a/b, b) # a is evenly divisible by b and a/b is also a power of b.
For the trivial case, b is a power of a if a=b.
However, we're not done. Because we are dividing by b, we have to make an exception for when b is zero.
And the other exception is when b = 1. Since when b=1, a/b is a, we will end up with infinite recursion.
So, putting it all together:
def is_power(a,b):
# trivial case
if (a==b): return True
# Exception Handling
if (b==0) or (b==1): return False # unless a==b==0 or a==b==1, which are handled by the trivial case above
# recursive case
return ((a%b)==0) and (is_power(a/b,b))
This example should fix your problem :
def is_power(a,b):
if a == 1:
return True
elif a%b == 0 and is_power(a/b, b) == True:
return True
else:
return False
You can use log.
import math
def is_power(a, b):
return math.log(a, b) % 1 == 0
I hope that this works, this one worked fine for me.
import math # I will use the math module for the next function
def is_power (a, b):
if b == 1 and a!= 1:
return False
if b == 1 and a == 1:
return True
if b == 0 and a!= 1:
return False
power = int (math.log(a, b) + 0.5)
return b ** power == a
Your solution is correct however you just need to remove ALL of the parenthesis in your if statement.
def ab(a, b):
c = b/a
if a%b == 0 and c%b == 0:
return True
else:
return False
print (ab(32, 2))

Python Recursion Exercise

I am doing exercise on Singpath and I am stuck at this question. This question is under recursion exercises but I have no idea what the question means.
A number, a, is a power of b if it is
divisible by b and a/b is a power of
b.
Write a function called is_power
that takes parameters a and b and
returns True if a is a power of b.
Update:
Just thought of the answer and I've posted it below.
It's a recursive definition of power. You are supposed to write the function
def is_power(a, b):
...
The definition give a general property. hint for the terminal case. if a and b are equals the function should answer true.
Think about what it will do, at present, if you give it, say a=32 and b=2. b*b will give you 4, 16, 256...
So, you have to keep track of the original b as you're calling your function recursively. You could have a third variable with a default value (original_b), but there's a way to do it without replacing b at all.
Look more closely at the information you are given:
A number, a, is a power of b if it is divisible by b and a/b is a power of b.
It says "... and a/b is a power of b". It does not say "... and a is a power of b*b". There is a reason for that: you don't get the same results with the two different definitions.
Now look at your code for the recursive call:
return is_power(a,b*b)
We don't care if a is a power of b*b; we care if a/b is a power of b. So why are we calling is_power(a, b*b) # is a a power of b*b? ? Instead, we should call... well, I think you can figure it out :)
Why it's different: let's say the recursion happens twice. When we start out calling the function, let's say b = 2. On the first recursion, we pass 2 * 2 = 4. On the next recursion, the input was 4, so we pass 4 * 4 = 16. But we skipped the check for 2 * 2 * 2 = 8. 8 is a power of 2, but if we call is_power(8, 2), then is_power(8,8) never happens, and then is_power(8, 16) returns False.
def isp(a,b):
if a%b==0 and isp(a/b,b):
return True
elif a/b==b:
return True
else:
return False
You should start with the trivial cases, there are two in fact: is_power(x,x) and is_power(1,x).
Once you have the edge case you just need to write down the definition correctly. It mentions a/b and b, but you wrote return is_power(a,b*b). Maybe you think that is the same, just scaled both arguments with b, but it is not. Think about the values of b in is_power(27,3).
Here is my answer...
def is_power(a,b):
if(a%b != 0):
return False
elif(a/b == 1):
return True
else:
return is_power(a/b,b)
def power(a,b):
if a<=b:
if a==b: return True
else:return False
elif a%b==0: return power(a/b,b)
else: return
You need to consider the edge case where a = 0 (which some of the answers above do). I just wanted to point in out in particular, because it's easy to see why a = 1 is an important edge case, but a = 0 is also important because if you don't acknowledge it in some way you may end up with infinite recursion.
If it helps, this is how I approached it:
def is_power(a, b):
if a == b or a == 1:
# a == b is the 'success' base case (a is a power of b)
# a == 1 is the success edge case where a is 1 (b ^ 0)
return True
elif a % b != 0 or a == 0:
# a % b != 0 is the 'failure' base case (a is not a power of b)
# a == 0 is the failure edge case where a is 0. If
# you don't acknowledge this case in some way, the function
# will recurse forever
return False
else:
# else, keep recursing
return is_power(a / b, b)
print is_power(8, 2) # True
print is_power(6, 2) # False
print is_power(0, 2) # False
print is_power(1, 2) # True
def is_power(a, b):
if a%b == 0 and a/b**b:
return True
else:
return False
is_power(10, 12)

Categories