Find the greatest common divisor - python

def gei(a, b):
'''
a, b: only positive integers! If you don't, we will make you. Max 1337
For extracting the juice of the numbers in the form of a common divider
'''
#Not Ruby, no to_i, but int()
smallest = int(abs(min(a, b)))
biggest = int(abs(max(a, b)))
print "You inputed: ", smallest, " and ", biggest, " their order doesn't matter."
print "Do you want to see guess numbers? Type 'yes', if you do! "
selection = raw_input()
print
print
#To evade infinite loops and too big numbers, we use count.
count = 0
ans = smallest
truth = str(selection) == str('yes')
def condition(ans, base):
ans1 = base % ans == 0
return ans1
while condition(ans, biggest) == False or condition(ans, smallest) == False:
ans -= 1
count += 1
if count >= 1337:
break
elif truth == True:
print ans
if truth == True:
print
print
print "After weeks of calculation, here is your greater common divider: "
return ans
So yeah, 8th grade informatics assignment to extract common greater dividers. I was wondering, maybe you guys know how can I make it less cumbersome? How to avoid using definition inside and naming so many variables?

import fractions
print fractions.gcd(4,8)
>>> 4
But you can also look at the source:
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
Reference: http://en.wikipedia.org/wiki/Euclidean_algorithm

Use Euclid's algorithm
int GCD(int a,int b){
if(b==0){
return a;
}
return GCD(b,a%b);
}

A few things can be improved in your code.
First off, truth is a truly poor variable name, since it doesn't really tell you what it's contents mean. I'd use something like show_work instead.
Next, you have an internal function that tells you a variable divides another evenly (returning a Boolean value). I'd suggest just using the modulus value directly, rather than coverting it to a bool with == 0, and you also don't need it to be in a function. Also, it's never necessary to compare a value to True or False. Just use the value itself (or use not to invert it). Putting these together will make your while loop's condition not biggest % ans and not smallest % ans.
Finally, you can use a better algorithm than trying every value one by one. Euclid's algorithm is a great way to calculate the Greatest Common Divisor quickly, and it's very easy to implement in Python (but I'll leave it to you).

This is nice an consise, and names no variable:
def gcd(a,b):
return max(d for d in xrange(1, min(a, b)+1) if a % d == b % d == 0)
print gcd(15, 25)
>>> 5
But please don't claim it as your own :)

Related

I don't see my error here - Trying to learn Python

I'm trying to become comfortable with python. I've been trying some simple activities that I've given in my beginning c++ classes when I was teaching. I did one involving functions and writing a file which worked flawlessly. I thought this one would be easier. It acts like it is in a silent endless loop, but it won't even let me trace it. Can someone see where I am going awry?
# Find Adam Numbers
def isAdamNumber(candidate):
isAdam = False
rev = reverse(candidate)
square = candidate * candidate
revsq = rev*rev
if revsq == reverse(square):
isAdam = True
return isAdam
def reverse(num):
rev=0
while num > 0:
rev = rev * 10 + num%10
num/=10
return rev
for x in range (11,25):
if isAdamNumber(x):
print(x, " is an adam number\n")
The quick fix is to change /= with the integer division version, //=
Inside the reverse function, you are going into an infinite loop. num value always will be greater than 0, therefore the while loop will continuously run. In python, you can get the reverse of the function without much effort. Convert the integer to string and reverse the string and now change the string back to integer.
def reverse(num):
num_str = str(num)[::-1]
return int(num_str)
I think this function definition can solve your problem.
To visualize the python to learn and teach, use this link
The problem has already been addressed by the other answers, so here's the expanded and simplified version of the slicing that's going on [this doesn't actually use slicing]:
def reverse(num):
rev = ''
num = str(num)
for i in range(len(num) - 1, -1, -1):
rev += num[i]
return int(rev)
This counts backward from the last element in the string version of num, and adds all the elements of num (in reverse order) to rev.
num > 0 is never False. Dividing a positive number by 10 repeatedly makes it smaller, but it never becomes zero, so the while loop keeps repeating.
Use //= instead. It rounds to the nearest integer, so it will reach 0.
This also wouldn't reverse numbers (unless I'm missing something). Alternatively, you can use
int(str(num)[::-1])
which converts the number to a string, reverses it using slicing, and turns it back into an integer.

Python math division operation returns 0

print "------------ EPIDEMIOLOGY --------------\n"
def divide(A,B):
return A/B
print " [Population] point Prevalence rate: "
A = input("Enter value for people with disease: " )
B = input("Enter value for total population: " )
prevalence = divide(A,B)
print " Population Prevalence rate is: ",prevalence
A and B are user input and do not know if they are integers or floats. My answer is always 0 when i run this program. (I'm new in Python). How do i fix this or change in my function to avoid this problem?
the input part of code works, the math does not.
You get the answer 0 because you are using Python2 and performing integer division. The fact that the population with disease cannot be higher than the total population is the reason that you get zero for every reasonable input (except when both values are the same).
Two fixes:
def divide(a,b):
if b == 0:
# decide for yourself what should happen here
else:
return float(a)/b
This will make sure that your function performs floating point division, not matter what numbers you pass to it. The second fix is that you should use raw_input in Python2 and cast the input to a number (float would be fine here).
a = float(raw_input("Enter value for people with disease: ")) # add error checking as needed
b = float(raw_input("Enter value for total population: " )) # add error checking as needed
The problem with input() is that it is equivalent to eval(raw_input()).
In python 2.x is performed integer division. If dividend is less than divisor, the operation returns zero.
So you have two options:
Make one of operands as float:
def divide(A,B):
return float(A)/B
import feature from Python 3
from __future__ import division
print "------------ EPIDEMIOLOGY --------------\n"
def divide(A,B):
return A/B

Python does not follow order of PEMDAS?

I am programming a catalan number generator for homework, and I am doing a recursive program in pytohon.
The program:
def catalan(n):
if n == 0:
c_f = 1
else:
c_f = ((4*n-2)/(n+1))*catalan(n-1)
return c_f
print catalan(10)
returns 5832, which is the wrong answer, but
def catalan(n):
if n == 0:
c_f = 1
else:
c_f = (4*n-2)*catalan(n-1)/(n+1)
return c_f
print catalan(10)
gives me 16796, which is the correct answer.
So does python not follow PEMDAS?
Just like PEMDAS, python evaluates expressions from left to right. It evaluates (4*n-2)/(n+1), stores it (call the result X), and then computes X/catalan(n-1).
The problem is, what is the value of X? (4*n-2)/(n+1) is not an integer for all values of n, but if you're passing in a value of n that is a python int you're performing integer division. The result is that the fractional part of the computation is discarded, and your computation goes off the rails.
The second iteration works because of a property of the catalan function is that the (4*n-2)*catalan(n-1) expression will be a multiple of n-1. This way, you leave the (potentially destructive) division to the end of the expression, and the mathematical properties of you computation save you.

Project Euler #4 with python. What;s wrong with my code?

I am trying to do project euler problem 4 using python. The problem statement goes like this:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
I wrote down a solution for it:
s=0
x=100
y=100
list=[]
z=x*y
def palindrome():
while z>=1:
s=s*10+z%10
z=z/10
if z==s:
list.append(z)
while x<=999:
while y<=999:
palindrome()
y=y+1
x=x+1
y=100
print list
It ended up giving an error along the lines of 'z referenced beyond assignment'.
I searched for a solution to this error before finally deciding to use the syntax 'global' to bypass this error.
s=0
x=100
y=100
list=[]
z=x*y
def palindrome():
global z
global s
global x
global y
global list
while z>=1:
s=s*10+z%10
z=z/10
if z==s:
list.append(z)
while x<=999:
while y<=999:
palindrome()
y=y+1
x=x+1
y=100
print list
Now it doesn't give an error, but it gives an empty list as output. I tried to debug the code by inserting print statements in between. The loops appear to work fine, as 'x' and 'y' print all the values they are supposed to. However, I get an empty list as an output to the print list command and 'z' does not apparently change values and is stuck at 100000 despite me using while loops to change the values of x and y.
I am at a loss on how to proceed from here.
The error you got was probably:
UnboundLocalError: local variable 'z' referenced before assignment
This means that z was not defined, at least not within the palindrome() function. Your solution of adding the global keyword is technically correct. However, as others have pointed out already, use of globals makes the code hard to follow.
It's not clear to me what palindrome() is supposed to do. Is it supposed to check if a number is a palindrome? Generate palindrome numbers? To fix this problem, you should think about structuring your code. There are many ways to do this, of course, and with time you will find your own style.
My advice, then, is to think about how you would solve this in general. If you don't know the solution, coding won't help you. Sometimes, when solving problems like this one, I write functions without declaring their bodies. You can do this top-down or bottom-up, both work. For example:
def is_palindrome(n):
""" Check if n is a palindrome number. """
pass
def multiples_of_3_digits():
""" Return all numbers that are the product of two 3-digit numbers ."""
pass
def main():
print max(n for n in multiples_of_3_digits() if is_palindrome(n))
This way you can focus on solving the problem, then on the actual coding. Maybe you will add helper functions or realize you can solve the problem in a more efficient way, but it's a start. Good luck!
min=100
max=999
max_palindrome = 0
for a in range(min,max + 1):
for b in range(a + 1, max + 1):
prod = a*b
if prod > max_palindrome and str(prod)==(str(prod)[::-1]):
max_palindrome = prod
print max_palindrome
Here we are only concerned with the maximum palindrome, and so we don’t spend any time storing other palindromes once they are known to be non-maximum. Also, the if statement first checks if the given product is larger than the maximum known palindrome before using the string cast and list slice to check whether or not the number is even a palindrome. This should speed up our code a bit since the greater than comparison will often fail, regardless of whether the product in question is a palindrome. When we run this, we get the following.
906609
Alternate Way:
I would discourage you to use the global variables because of the reasons pointed out by others. I would also like you to refer to Andre's approach as it will teach you to organize yourself. In this approach too I will be using 2 functions is_palindrome(num) [to check if the number is palindrome or not] and find_max_palindrome [to find the largest palindrome]
def is_palindrome(num):
reversed = 0
original = num
if num < 10:
return True
if num % 10 == 0:
return False
while num >= 1:
reversed = (reversed * 10) + (num % 10)
num = num/10
if original == reversed:
return True
else:
return False
def find_max_palindrome():
max_palindrome = 0
a = 999
b = 999
prod = 0
while a > 99:
b = 999
while b >= a:
prod = a*b
if prod > max_palindrome and is_palindrome(prod):
max_palindrome = prod
b = b -1
a = a - 1
return max_palindrome
print find_max_palindrome()

How can I use recursion to find palindromes using Python?

I've just started exploring the wonders of programming. I'm trying to write a code to identify numeric palindromes. Just looking at numbers and not texts. I'm trying to learn to use recursion here. But I'm just not getting anywhere and I can't figure out what's wrong with it.
My idea was to check first string vs the last, then delete these two if they match, and repeat. Eventually there'll be nothing left (implying it is a palindrome) or there will be a couple that doesn't match (implying the reverse).
I know there are better codes to finding palindromes in but I just wanted to try my hand at recursion.
So what's wrong?
def f(n):
global li
li=list(str(n))
if (len(li)==(1 or 0)):
return True
elif li[len(li)-1]==li[0]:
del li[0]
del li[len(li)-1]
if len(li)==0:
return True
if len(li)>0:
global x
x=''.join(li)
str(x)
f(x)
else:
return False
Thanks in advance!
A few comments
Why are x and li globals? In recursion, all variables should be local.
Why are you converting back and forth between str and list? You can subscript both of them
You need to return the result of your recursive call: return f(x)
Try these suggestions, and see how it works out.
Before looking into it too much, if (len(li)==(1 or 0)): doesn't do what you're expecting it to do. (1 or 0) will always evaluate to 1.
You probably want:
if len(li) in (1, 0):
There are a couple of problems with your solution. Let me analyse them line by line.
You don't need global statements if you don't intend to change variables outside of function scope. Thus, I removed two lines with global from your code.
li=list(str(n)): casting a string to a list is unnecessary, as a string in Python has a similar interface to an immutable list. So a simple li = str(n) will suffice.
if (len(li)==(1 or 0)):: although it looks OK, it is in fact an incorrect way to compare a value to a few other values. The or operator returns the first "true" value from its left or right operand, so in this case it always returns 1. Instead, you can use the in operator, which checks whether the left operand is an element of a right operand. If we make the right operand a tuple (1, 0), all will be well. Furthermore, you don't need parentheses around the if statement. You should write: if len(li) in (1, 0):
elif li[len(li)-1]==li[0]: is fine, but we can write this shorter in Python, because it supports negative list indexing: elif li[-1] == li[0]:
Because we don't use lists (mutable sequences) because of point 2., we can't do del li[0] on them. And anyway, removing the first element of a list is very inefficient in Python (the whole list must be copied). From the very same reason, we can't do del li[len(li)-1]. Instead, we can use the "splicing" operator to extract a substring from the string: li = li[1:-1]
if len(li)==0: is unnecessary long. In Python, empty strings and lists resolve to False if tested by an if. So you can write if not li:
if len(li)>0:: You don't have to check again if li is not empty -- you checked it in point 6. So a simple else: would suffice. Or even better, remove this line completely and unindent the rest of the function, because the body of the if in 6. contains a return. So if we didn't enter the if, we are in the else without writing it at all.
x=''.join(li): We don't need to convert our string to a string, because of the decision made in 2. Remove this line.
str(x): This line didn't do anything useful in your code, because str() doesn't modify its argument in place, but returns a new value (so x = str(x) would have more sense). You can also remove it.
f(x): This is a valid way to call a recursive function in Python, but you have to do something with its value. Return it perhaps? We'll change it to: return f(li) (as we don't have an x variable any more).
We end up with the following code:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
if not li:
return True
return f(li)
else:
return False
It's almost what we need, but still a little refinement can be made. If you look at the lines if not li: return True, you'll see that they are not necessary. If we remove them, then f will be called with an empty string as the argument, len(li) will equal 0 and True will be returned anyway. So we'll go ahead and remove these lines:
def f(n):
li = str(n)
if len(li) in (1, 0):
return True
elif li[-1] == li[0]:
li = li[1:-1]
return f(li)
else:
return False
And that's it! Good luck on your way to becoming a successful programmer!
Split the whole show out into a list, then just:
def fun(yourList):
if yourList.pop(0) == yourList.pop(-1):
if len(yourList) < 2:
return True # We're a palindrome
else:
return fun(yourList)
else:
return False # We're not a palindrome
print "1234321"
print fun(list("1234321")) # True
print "6234321"
print fun(list("6234321")) # False
def palindrome(n):
return n == n[::-1]
It's hard to tell what you intend to do from your code, but I wrote a simpler (also recursive) example that might make it easier for you to understand:
def is_palindrome(num):
s = str(num)
if s[0] != s[-1]:
return False
elif not s[1:-1]:
return True
else:
return is_palindrome(int(s[1:-1]))
number = int(raw_input("Enter a number: "))
rev = 0
neg = number
original = number
if (number < 0):
number = number * -1
else:
number = number
while ( number > 0 ):
k = number % 10
number = number / 10
rev = k + ( rev * 10 )
if (number < 1):
break
if ( neg < 0 ):
rev = ( rev * -1)
else:
rev = (rev)
if ( rev == original):
print "The number you entered is a palindrome number"
else:
print "The number you entered is not a palindrome number"
This code even works for the negative numbers i am new to programming in case of any errors
dont mind.

Categories

Resources