Making a GCF calculator in python - python

I'm making a calculator in python that takes in two numbers and returns the greatest common factor of it. When I create a function that returns the same numbers of the two lists of factors, I keep getting a 'index' error even if I stated
if len(one) == 0 and len(two) == 0:
here's my code:
def work(one, two):
for i in range(len(one)):
for j in range(len(two)):
if len(one) != 0 and len(two) != 0:
if one[i] == two[j]:
one.pop(i)
two.pop(j)
if len(one) == 0 or len(two) == 0:
break
else:
work(primeF, primeF2)
break
work(primeF, primeF2)
What could I do to fix this?

You can greatly simplify your code by using what is already available in Python's standard library:
>>> import fractions
>>> work = fractions.gcd
>>> work(12345, 67890)
15
The fractions.gcd function should do exactly what you want without the need for more code. Here is a copy of the function from the module's 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

I think that instead of checking whether the list length is 0, you need to be checking that the list is long enough to include your index.

There is an even easier way to do it without modules (I just used time for supplements)
import time
def gcf (num1, num2): #The Actual Calculator
if num1 > num2:
num1, num2 = num2, num1
for x in range (num1, 0, -1):
if num1 % x == 0 and num2 % x == 0:
return x
def run(): #This section is defined so that it can be run multiple times
num1 = int(input("First Number: ")) #First number
num2 = int(input("Second Number: ")) #Second number
print (str (gcf (num1, num2)))
run_again = input("Run again? y or yes for yes: ")
if run_again == "yes" or run_again == "Y" or run_again == "Yes" or
run_again == "y":
run()
elif run_again == "hello":
print("hi")
run()
else:
print("Goodbye!")
time.sleep(1.5)
quit()
#Runs the code
run()

Related

When I attempt to execute my recursive function with odd numbers ,i have a kern problem

There is a problem with odd numbers.
When I run the function on even numbers, the code works.
#recursive demo function1
#Even nums
def evenNum(num):
if num % 2 != 0:
print("enter a even number")
if num == 2:
return num
else:
return evenNum(num-2)
evenNum(5)
output : Canceled future for execute_request message before replies were done
The second if should be changed to elif. When number is odd it prints "Enter a even number" and then compares it to 2. As it is different, it calls the function again.
Here is fixed code
def evenNum(num):
if num % 2 != 0:
print("enter a even number")
elif num == 2:
return num
else:
return evenNum(num-2)
evenNum(5)
Btw. make sure the number is greater than 0.
#recursive function1
#positive Even nums
def evenNum(num):
print(num)
if num % 2 != 0:
return print("enter an even number")
elif num == 2:
pass
else:
return evenNum(abs(num)-2)
evenNum(5)
Thank you for your valuable advice.
I learned some things about return and kern error.

Python programming question - numbers and integers and division

Divisible challenge
Write a program that asks the user for two numbers. The program should output whether the two numbers are exactly divisible by each other. If not, it should return the remainder. If the user enters a 0 the program should give an error message.
so far I've done this:
num1 = int(input("Enter a number: "))
num2 = int(input("Enter a number: "))
answer1 = num1/num2
answer2 = num2/num1
if num1/num2 == answer1(int) or num2/num1 == answer2(int):
print("Exactly divisible")
elif num1 == 0 or num2 == 0:
print("Error: you cannot divide by 0")
elif num1/num2 != answer1(int) or num2/num1 != answer2(int):
print("Not Exactly divisible")
please help...
I would approach this way
first check the zero case, in that case the code terminates faster
num1 = int(input("Enter a number: "))
num2 = int(input("Enter a number: "))
# answer1 = num1/num2
# answer2 = num2/num1
def divisible_by_each_other(num1, num2):
if (num1 == 0) or (num2==0):
print("Error do not enter 0")
#check divisibility
elif (num1%num2 == 0 ) or (num2%num1 == 0 ):
print("Exactly divisible")
else:
print("Not Exactly divisible")
high,low= max(num1,num2),min(num1,num2)
print("The remainder is ", high%low)
divisible_by_each_other(num1, num2)
answer1(int) is not the correct way to convert to an integer, it's int(answer1).
Since you already divided the numbers, you could use
if answer1 == int(answer1) or answer2 == int(answer2):
But you're making this much more complicated than it needs to be. Modulus is a simpler way to test divisibility.
if num1 % num2 == 0 or num2 % num1 == 0
You also should check if either of the numbers is zero before you try to use division or modulus. Otherwise, you'll get an error due to trying to divide by 0, which is what you're trying to prevent with this check.
If they're not divisible by each other, get the remainder of the larger divided by the smaller:
else:
return max(num1, num2) % min(num1, num2)
Here's the full, simplified code:
num1 = int(input("Enter a number: "))
num2 = int(input("Enter a number: "))
higher = max(num1, num2)
lower = min(num1, num2)
if num1 == 0 or num2 == 0:
print("Error: you cannot divide by 0")
elif higher % lower == 0
print("Exactly divisible")
else:
print(higher % lower)

How to change my code

If I give negative numbers this code does not function any more and I don't know how to stop it if I put for example a string or something that doesn't have sense. Help me please!!
def computeHCF(x,y):
if x>y:
smaller = y
else:
smaller = x
for i in range(1, smaller+1):
if((x % i == 0) and (y % i == 0)):
hcf = i
return hcf
while True:
num1 = int(input("Enter the first number: "))
num2 = int(input("Enter the second number: "))
print("The H.C.F. of", num1,"and", num2,"is", computeHCF(num1, num2))
continue;
else:
print("You write something that doesn't have any sense!")
You have to make python first check for strings in the input.
Then check for negative numbers,
If none of these two errors are present it goes ahead to run your code
But if they are let it exit before giving an error
Like so:
def computeHCF(x,y):
if type(x) is str or type(y) is str:
print("You wrote something that doesn't have any sense!")
exit()
elif x < 0 or y < 0 :
print("You wrote something that doesn't have any sense!")
exit()
elif x>y:
smaller = y
elif y<x:
smaller = x
for i in range(1, smaller+1):
if((x % i == 0) and (y % i == 0)):
hcf = i
return hcf
while True:
num1 = (input("Enter the first number: "))
num2 = (input("Enter the second number: "))
print("The H.C.F. of", num1,"and", num2,"is", computeHCF(num1, num2))
continue;
We can simulate what happens in your code when the result is not what we expect.
We noticed that if we insert a negative number, the program stops.
so let's assume num1 = -4 and num2 = 2
def computeHCF(x,y): # x = -4, y = 2
if x>y: # we don't meet this condition
smaller = y
else: # we meet this condition
smaller = x # smaller value is -4
for i in range(1, smaller+1): # there is nothing in range(1, -3)!!
# we do not enter here
if((x % i == 0) and (y % i == 0)):
hcf = i
return hcf # hcf value has never been retrived, so an error will be raised here
you can solve this problem in many ways, two of them are:
set hfc with a base value, so if the conditions in the for loop are not met, the base value will be returned:
def computeHCF(x,y):
hcf = None
this code will return:
('The H.C.F. of', -4, 'and', 2, 'is', None)
or by having the absolute value of x and y:
def computeHCF(x,y):
x = abs(x)
y = abs(y)
this code will return:
('The H.C.F. of', -4, 'and', 2, 'is', 2)
We also see that if we insert a string or something that can't be interpreted as an int, another error is raised.
This time, the error happens when you read the input:
num1 = int(input("Enter the first number: "))
num2 = int(input("Enter the second number: "))
in this two lines, you convert anything that the user input to an int, but strings like "Hello World!" can't be converted into an int.
One of the many way to solve this problem, is to use try/except: you try to read the input as an int, but if an error occurs, you do something else.
try:
num1 = int(input("Enter the first number: "))
num2 = int(input("Enter the second number: "))
print("The H.C.F. of", num1,"and", num2,"is", computeHCF(num1, num2))
continue
except:
print("You write something that doesn't have any sense!")
continue
with this code, the result of the inputs "Hello" and "World!" will be:
"You write something that doesn't have any sense!"
you catch also the error generated by the function computeHCF(x,y) when x = 0 or y = 0.
At last, you can erase your last two lines, with the "else" statement. That else will be executed only when the condition of the while loop is False, but True is always True!
in the end, your code could be like:
def computeHCF(x,y):
x = abs(x)
y = abs(y)
# or hcf = None
if any([type(x)!=int,type(y)!=int]):
return hcf
if x>y:
smaller = y
else:
smaller = x
for i in range(1, smaller+1):
if((x % i == 0) and (y % i == 0)):
hcf = i
return hcf
while True:
try:
num1 = int(input("Enter the first number: "))
num2 = int(input("Enter the second number: "))
print("The H.C.F. of", num1,"and", num2,"is", computeHCF(num1, num2))
except:
print("You write something that doesn't have any sense!")
continue

Random Maths Program

thanks for taking time to read this.
I have to create a program that generates 10 random maths questions based around =, - and *. I have the program working but everytime I run it after the main program it prints "none" even though that's not in my program.Any help at all would be much appreciated. Thank you.
import random
print ("Welcome")
name=input("What's your name?")
print("Nice to meet you", name, ",you will be given 10 multiplication, addition and subtraction questions.")
Num1 = random.randint(1,12)
Num2 = random.randint(1,12)
sign = random.randint(1,3)
if sign == 1: # If the random number generated is 1
question = Num1 + Num2
rightanswer1 = Num1 + Num2
answer1=input(print("What is", question ,"?"))
if answer1 == rightanswer1:
print("Well Done!")
if answer1 != rightanswer1:
print("Sorry, that's incorrect, the answer was", rightanswer1)
if sign == 2:
question = Num1 - Num2
rightanswer2 = Num1 - Num2
answer2=input(print("What is", Num1, "-", Num2 ,"?"))
if answer2 == rightanswer2:
print("Well done!")
elif answer2 != rightanswer2:
print("Sorry, that's incorrect, the answer was", rightanswer2)
if sign == 3:
question = Num1 * Num2
rightanswer3 = Num1 * Num2
answer3=input(print("What is", Num1, "x", Num2 ,"?"))
if answer3 == rightanswer3:
print("Well done!")
elif answer3 != rightanswer3:
print("Sorry, that's incorrect, the answer was", rightanswer3)`
> Welcome
> What's your name? John
> Nice to meet you John ,you will be given 10 multiplication, addition and subtraction questions.
> What is 12 x 3 ?
> None 36
> Sorry, that's incorrect, the answer was 36
I think you are using python 3. In python 3 input is like raw_input in python 2. So you get the string as input. So convert it into int
var = int(input("Enter a number: "))
So in your code make it as
print("What is", Num1, "x", Num2 ,"?")
answer3 = input()
answer3 = int(answer3)
See this:
whats-the-difference-between-raw-input-and-input-in-python3-x
I'm reluctant to just give you an answer that just does it for you, so instead i'll provide you with a few hints to improve things. (i.e. this isn't an answer, just too large of a comment - and more like a codereview answer)
First off, you use a structure like this:
if x == 1:
#do something
if x == 2:
#do something else
...
In this case, which it makes no difference, it is easier to read if you use the if syntax as intended:
if <condition>:
#do this if the above test is true.
elif <more conditions>:
#do this only if the first test is false and this one is true
elif <more conditions>:
#same as above, except for the second test must be false too
else:
#do this if all the above tests are false
So you could use this something like:
if sign == 1:
...
elif sign == 2:
...
elif sign == 3:
...
else:
# something weird happened...
Which would make that section of the program easier to follow.
The same thing can be done with the if answer1 == rightanswer1: sections;
if answer1 == rightanswer1:
#correct!
else:
#incorrect.
That would be a clearer was to do it. You seem to have used the if...elif style in a couple of them, but not the first one.
Once you have this, it will be a little clearer.
The next way you could improve things is by removing duplicated code. You don't need separate branches for each sign, you can just roll it all into one:
number1 = randint(1,12)
number2 = randint(1,12)
op = randint(1,3)
question_string = "%d %s %d = ?" % (number1, number2, ["+", "-", "*"][op])
result = None
if op == 1:
result = number1 + number2
elif op == 2:
result = number1 - number2
elif op == 3:
result = number1 * number2
This will do most of the logic for you, and generate the strings you want, without duplicating all of the other code.
Small changes like this can make things much more readable.
It's printing None because the print() function returns None and you're passing that value of None from print() as the prompt to your input() functions. Eg,
answer3=input(print("What is", Num1, "x", Num2 ,"?"))
So print("What is", Num1, "x", Num2 ,"?") prints its stuff, and returns None, which then gets printed as the prompt by input().
A simple way to fix this is to just move your print() function calls out of your input() functions.
Eg,
print("What is", Num1, "x", Num2 ,"?")
answer3=input()
However, there's another major problem with your program: the rightanswer variables are ints, but the inputted answers are strings. To compare them properly they need to be the same type. So you should either convert the inputted answers to int, or alternatively, convert the rightanswers to str.
There are two problems with how you use the input function:
You misuse the prompt argument
You forget to convert the result
First, have a better look at the reference of the input function
The prompt argument
input takes a string as argument that will be displayed ("prompted") to the user to indicate that the program is waiting an input. The print function also displays a string to the user, but it doesn't return anything. It does its job and that's all (and in Python a function that returns nothing, returns None). That's what input gets to display, so it displays None. You should use format instead. It will format and return the formatted string that input can display:
answer1_as_str=input("What is {} ?".format(question))))
or
answer2_as_str=input("What is {:d} - {:d} ?".format(Num1, Num2)))
The return value
input returns the user input as a string contrary to python 2 (i.e. exactly as entered). So you have to convert the input to the desired type if you need it. If you type 10 for example, the input will return "10". If you need an int, you have to convert it yourself.
answer1 = int(answer1_as_str)
It looks like you don't really understand how input() works. You might also want to review the different datatypes and conditional statements. Other than that, it was a very good attempt. Here's my solution:
from random import randint
print("Welcome")
name = input("What's your name?\n")
print("Nice to meet you " + name + ", you will be given 10 multiplication, addition and subtraction questions.")
for i in range(10):
print("\nProblem " + str(i+1))
num1 = randint(1,12)
num2 = randint(1,12)
sign = randint(1,3)
if sign == 1:
question = str(num1) + " + " + str(num2)
answer = num1 + num2
elif sign == 2:
question = str(num1) + " - " + str(num2)
answer = num1 - num2
else:
question = str(num1) + " x " + str(num2)
answer = num1 * num2
user_answer = input("What is " + question + "? ")
if user_answer == str(answer):
print("Well done!")
else:
print("Sorry, that's incorrect, the answer was", answer)

Python: How to prevent questions with negative answers being randomly generated

My task is to create a maths quiz for primary school children. this is what I have done so far:
import random
import math
def test():
num1=random.randint(1, 10)
num2=random.randint(1, 10)
ops = ['+', '-', '*']
operation = random.choice(ops)
num3=int(eval(str(num1) + operation + str(num2)))
print ("What is {} {} {}?".format(num1, operation, num2))
userAnswer= int(input("Your answer:"))
if userAnswer != num3:
print ("Incorrect. The right answer is {}".format(num3))
return False
else:
print ("correct")
return True
username=input("What is your name?")
print ("Welcome "+username+" to the Arithmetic quiz")
correctAnswers=0
for question_number in range(10):
if test():
correctAnswers +=1
print("{}: You got {} answers correct".format(username, correctAnswers))
What I now need to do is make my program only create questions with positive answers. e.g nothing like 3-10=-7
I've tried searching everywhere online but I cant find anything so I've turned to you guys for help. Any help will be appreciated :)
What I would recommend is:
#Random code...
if num1<num2:
num1, num2 = num2, num1
#Rest of program
So that 3 - 7 = -4 becomes 7 - 3 = 4
The reason I recommend doing this is that the answer would still be the same as the previous equation, just positive instead of negative, so you are still testing the same numbers.
Keep the larger number on the left of the expression, also use operator instead of eval:
from operator import add, sub, mul
def test():
num1 = random.randint(1, 10)
num2 = random.randint(1, 10)
d = {"+": add, "-": sub, "*": mul}
operation = random.choice(list(d)))
num1 = max(num1, num2)
num2 = min(num1, num2)
num3 = d[operation](num1, num2)
print("What is {} {} {}?".format(num1, operation, num2))
userAnswer = int(input("Your answer:"))
if userAnswer != num3:
print("Incorrect. The right answer is {}".format(num3))
return False
else:
print("correct")
return True
username = input("What is your name?")
print("Welcome {} to the Arithmetic quiz".format(username))
correctAnswers = sum(test() for question_number in range(10))
print("{}: You got {} answers correct".format(username, correctAnswers))
Or as #jonclements suggests sorting will also work:
num2, num1 = sorted([num1, num2])
On another note you should really be using a try/except to verify the user input and cast to an int otherwise the first value that cannot be cast to an int your program will crash.
You can choose the numbers such that num2 will be between 1 and num1 like:
num1=random.randint(1, 10)
num2=random.randint(1, num1)
or that num1 > num2:
n1=random.randint(1, 10)
n2=random.randint(1, 10)
num1 = max(n1,n2)
num2 = min(n1,n2)
i would go with the first option. no extra variables, no extra lines.
after the code that chooses the random numbers you can add this while loop:
while num3<0:
num1=random.randint(1, 10)
num2=random.randint(1, 10)
ops = ['+','-','*']
operation = random.choice(ops)
num3=int(eval(str(num1) + operation + str(num2)))
It will enter this loop every time the answer is negative. This will ensure that the answer is positive when the program quits the loop.
A change in one line should do it:
if num1 > num2:
num3=int(eval(str(num1) + operation + str(num2)))
else:
num3=int(eval(str(num2) + operation + str(num1)))

Categories

Resources