This code is essentially correct. You have your answer at list_fac[-1]
, if it isn't 1. You can fix this by iterating from range(1, x + 1)
:
def gcf(num1, num2):
list_fac = []
x = max(num1, num2)
y = min(num1, num2)
for i in range(1, x + 1):
if x % i == 0:
list_fac.append(i)
for t in list_fac:
if y % t != 0:
list_fac.remove(t)
return list_fac[-1] if list_fac else 0
if __name__ == "__main__":
print(gcf(10, 20)) # => 10
However, the code is inefficient and difficult to follow. For example, the inner loop does not need to iterate twice over list_fac
(list.remove()
traverses the whole list).
You only need consider whether the last element added is also divisible by zero. Nor is it necessary to keep the entire list in memory since we only care about the last thing added (largest element so far):
def gcf(num1, num2):
greatest = 0
x = max(num1, num2)
y = min(num1, num2)
for i in range(1, x + 1):
if x % i == 0 and y % i == 0:
greatest = i
return greatest
I recommend using the Euclidean Algorithm as follows (see the linked article or this thread for details on why the complexity is an improvement on linear):
def gcd(a, b):
while b:
a, b = b, a % b
return a
Even easier, the folks at Python have a builtin:
Python 3.7.2 (default, Mar 11 2019, 20:44:31)
[GCC 4.8.4] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from math import gcd
>>> gcd(10, 20)
10
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:43:06) [MSC v.1600 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from fractions import gcd
>>> gcd(10, 20)
10
Here's a quick test validating your routine:
from random import randint
from math import gcd
def gcf(num1, num2):
list_fac = []
x = max(num1, num2)
y = min(num1, num2)
for i in range(1, x + 1):
if x % i == 0:
list_fac.append(i)
for t in list_fac:
if y % t != 0:
list_fac.remove(t)
return list_fac[-1] if list_fac else 0
if __name__ == "__main__":
passes = 0
tests = 10000
for i in range(tests):
a, b = randint(0, 100), randint(0, 100)
if gcd(a, b) == gcf(a, b):
passes += 1
print(f"{passes}/{tests} passed") # => 10000/10000 passed
Quick benchmark:
gcd 0.7560891520042787
gcf 39.11557542099763
gcf improved 32.58505471699755
import timeit
from math import gcd
def gcf(num1, num2):
list_fac = []
x = max(num1, num2)
for i in range(2,x + 1):
if x % i == 0:
list_fac.append(i)
y = min(num1, num2)
for t in list_fac:
if y % t != 0:
list_fac.remove(t)
def gcf2(num1, num2):
greatest = 0
x = max(num1, num2)
y = min(num1, num2)
for i in range(1, x + 1):
if x % i == 0 and y % i == 0:
greatest = i
return greatest
def a(): gcd(20, 125)
def b(): gcf(20, 125)
def c(): gcf2(20, 125)
if __name__ == '__main__':
print("gcd", timeit.timeit("a()", setup="from __main__ import a"))
print("gcf", timeit.timeit("b()", setup="from __main__ import b"))
print("gcf improved", timeit.timeit("c()", setup="from __main__ import c"))