Greatest Common Divisor

Introduction

The greatest common divisor \(GCD(a,b)\) of two non-negative integers (a and b) which are not both equal to 0 is the greatest integer d that divides both a and b. The goal here is to implement the Euclidean Algorithm for computing the GCD.

Problem Description

  Description
Task Given two integers \(a\) and \(b\), find their greatest common divisor.
Input The two integers \(a\) and \(b\) are given on the same line separated by a space.
Constraints \(1 \le a,b \le 2 \cdot 10^9\)
Output GCD(a,b)

Imports

# python standard library
from datetime import (
    datetime,
    timedelta,
)

Samples

Input Output
18 35 1
28851538 1183019 17657
SAMPLES = {(18, 35): 1,
	   (28851538, 1183019): 17657}
MAX_TIME = timedelta(5)
MAX_INPUT = 2 * 10**9
def time_two_inputs(implementation, tag, a_and_b, expected, max_time=MAX_TIME, max_input=MAX_INPUT):
    """Time the implementation

    Args:
     implementation: callable to time
     tag (str): name for the output
     a_and_b (tuple): inputs for the implementation
     expected (int): the expected output of the implementation

    Raises:
     AssertionError: output was wrong or it took too long
    """
    a, b = a_and_b
    assert a <= max_input, "a too large: {}".format(a)
    assert b <= max_input, "b too large: {}".format(b)
    print("Starting {}".format(tag))
    start = datetime.now()
    actual = implementation(a, b)
    elapsed = datetime.now() - start
    print("Elapsed time: {}".format(elapsed))
    assert actual == expected, "Expected: {} Actual: {}".format(expected, actual)
    assert elapsed <= MAX_TIME, "Took too long: {}".format(elapsed)
    return

Naive GCD

def gcd_naive(a, b):
    """Naive implementation of GCD

    Args:
     a, b: non-negative integers
    """
    current_gcd = 1
    for d in range(2, min(a, b) + 1):
	if a % d == 0 and b % d == 0:
	    if d > current_gcd:
		current_gcd = d
    return current_gcd
for inputs, answer in SAMPLES.items():
    time_it(gcd_naive, "Naive", inputs, answer)

This fails the grader.

Failed case #10/22: time limit exceeded Input: 100000000 100000000 Your output: stderr: (Time used: 9.97/5.00, memory used: 9887744/536870912.)

Modulus Version

This is a variation on Euclid's Algorithim where you repeatedly use the remainder of \(\frac{a, b}\) to replace \(b\) until there is no remainder (\(b=0\)).

def gcd_modulus(a, b):
    """finds the GCD of a and b

    Args:
     a, b: non-negative integers

    Returns:
     int: the GCD of a and b
    """
    while b != 0:
	a, b = b, a % b
    return a
for inputs, answer in SAMPLES.items():
    time_it(gcd_modulus, "Modulus", inputs, answer)
a_b = 100000000, 100000000
start = datetime.now()
expected = gcd_naive(*a_b)
print("Elapsed: {}".format(datetime.now() - start))

My computer appears to be faster than the grader, but it still fails.

time_it(gcd_modulus, "Modulus", a_b, expected)