Skip to content

gcd_of_n_numbers #8057

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 24 commits into from
Jan 10, 2023
Merged
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
83aa457
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
1dd1284
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
89b8336
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
3747c46
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 27, 2022
8996186
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
bc3ea36
Merge branch 'master' of https://github.com/balakhaniyan/Python
balakhaniyan Dec 27, 2022
c774f82
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 27, 2022
0200bd6
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
e684640
Merge branch 'master' of https://github.com/balakhaniyan/Python
balakhaniyan Dec 27, 2022
da603f6
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
95e67aa
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Dec 27, 2022
27f48bd
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
e02a30c
Merge branch 'master' of https://github.com/balakhaniyan/Python
balakhaniyan Dec 27, 2022
2f660fc
add maths/Gcd of N Numbers
balakhaniyan Dec 27, 2022
4099e95
more pythonic
balakhaniyan Jan 10, 2023
ec207a8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 10, 2023
8406035
more pythonic
balakhaniyan Jan 10, 2023
99af232
merged
balakhaniyan Jan 10, 2023
d5681d8
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 10, 2023
db4f11b
merged
balakhaniyan Jan 10, 2023
8b321ba
more readable
balakhaniyan Jan 10, 2023
b7473dd
merged
balakhaniyan Jan 10, 2023
a230d7e
more readable
balakhaniyan Jan 10, 2023
d351516
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Jan 10, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions maths/gcd_of_n_numbers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
"""
Gcd of N Numbers
Reference: https://en.wikipedia.org/wiki/Greatest_common_divisor
"""

from collections import Counter


def get_factors(
number: int, factors: Counter | None = None, factor: int = 2
) -> Counter:
"""
this is a recursive function for get all factors of number
>>> get_factors(45)
Counter({3: 2, 5: 1})
>>> get_factors(2520)
Counter({2: 3, 3: 2, 5: 1, 7: 1})
>>> get_factors(23)
Counter({23: 1})
>>> get_factors(0)
Traceback (most recent call last):
...
TypeError: number must be integer and greater than zero
>>> get_factors(-1)
Traceback (most recent call last):
...
TypeError: number must be integer and greater than zero
>>> get_factors(1.5)
Traceback (most recent call last):
...
TypeError: number must be integer and greater than zero

factor can be all numbers from 2 to number that we check if number % factor == 0
if it is equal to zero, we check again with number // factor
else we increase factor by one
"""

match number:
case int(number) if number == 1:
return Counter({1: 1})
case int(num) if number > 0:
number = num
case _:
raise TypeError("number must be integer and greater than zero")

factors = factors or Counter()

if number == factor: # break condition
# all numbers are factors of itself
factors[factor] += 1
return factors

if number % factor > 0:
# if it is greater than zero
# so it is not a factor of number and we check next number
return get_factors(number, factors, factor + 1)

factors[factor] += 1
# else we update factors (that is Counter(dict-like) type) and check again
return get_factors(number // factor, factors, factor)


def get_greatest_common_divisor(*numbers: int) -> int:
"""
get gcd of n numbers:
>>> get_greatest_common_divisor(18, 45)
9
>>> get_greatest_common_divisor(23, 37)
1
>>> get_greatest_common_divisor(2520, 8350)
10
>>> get_greatest_common_divisor(-10, 20)
Traceback (most recent call last):
...
Exception: numbers must be integer and greater than zero
>>> get_greatest_common_divisor(1.5, 2)
Traceback (most recent call last):
...
Exception: numbers must be integer and greater than zero
>>> get_greatest_common_divisor(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
1
>>> get_greatest_common_divisor("1", 2, 3, 4, 5, 6, 7, 8, 9, 10)
Traceback (most recent call last):
...
Exception: numbers must be integer and greater than zero
"""

# we just need factors, not numbers itself
try:
same_factors, *factors = map(get_factors, numbers)
Copy link
Member

@cclauss cclauss Jan 10, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

except TypeError as e:
raise Exception("numbers must be integer and greater than zero") from e

for factor in factors:
same_factors &= factor
# get common factor between all
# `&` return common elements with smaller value (for Counter type)

# now, same_factors is something like {2: 2, 3: 4} that means 2 * 2 * 3 * 3 * 3 * 3
mult = 1
# power each factor and multiply
# for {2: 2, 3: 4}, it is [4, 81] and then 324
for m in [factor**power for factor, power in same_factors.items()]:
mult *= m
return mult


if __name__ == "__main__":
print(get_greatest_common_divisor(18, 45)) # 9