98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# IMPORTS
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
from src.thirdparty.types import *;
|
|
from src.thirdparty.maths import *;
|
|
|
|
from models.generated.config import *;
|
|
from src.core.utils import *;
|
|
from src.models.euklid import *;
|
|
from src.algorithms.euklid.display import *;
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# EXPORTS
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
__all__ = [
|
|
'euklidean_algorithm',
|
|
];
|
|
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
# METHOD euklidean algorithm
|
|
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
def euklidean_algorithm(
|
|
a: int,
|
|
b: int,
|
|
verbose: bool = False,
|
|
) -> Tuple[int, int, int]:
|
|
'''
|
|
Führt den Euklideschen Algorithmus aus, um den größten gemeinsamen Teiler (ggT, en: gcd)
|
|
von zwei positiven Zahlen zu berechnen.
|
|
'''
|
|
################
|
|
# NOTE:
|
|
# Lemma: gcd(a,b) = gcd(mod(a, b), b)
|
|
# Darum immer weiter (a, b) durch (b, gcd(a,b)) ersetzen, bis b == 0.
|
|
################
|
|
steps = [];
|
|
d = 0;
|
|
while True:
|
|
if b == 0:
|
|
d = a;
|
|
steps.append(Step(a=a, b=b, gcd=d, div=0, rem=a, coeff_a=1, coeff_b=0));
|
|
break;
|
|
else:
|
|
# Berechne k, r so dass a = k·b + r mit k ≥ 0, 0 ≤ r < b:
|
|
r = a % b;
|
|
k = math.floor(a / b);
|
|
# Speichere Berechnungen:
|
|
steps.append(Step(a=a, b=b, gcd=0, div=k, rem=r, coeff_a=0, coeff_b=0));
|
|
# ersetze a, b durch b, r:
|
|
a = b;
|
|
b = r;
|
|
|
|
################
|
|
# NOTE:
|
|
# In jedem step gilt
|
|
# a = k·b + r
|
|
# und im folgenden gilt:
|
|
# d = coeff_a'·a' + coeff_b'·b'
|
|
# wobei
|
|
# a' = b
|
|
# b' = r
|
|
# Darum:
|
|
# d = coeff_a'·b + coeff_b'·(a - k·b)
|
|
# = coeff_b'·a + (coeff_a' - k·coeff_b)·b
|
|
# Darum:
|
|
# coeff_a = coeff_b'
|
|
# coeff_b = coeff_a' - k·coeff_b
|
|
################
|
|
coeff_a = 1;
|
|
coeff_b = 0;
|
|
for step in steps[::-1][1:]:
|
|
(coeff_a, coeff_b) = (coeff_b, coeff_a - step.div * coeff_b);
|
|
step.coeff_a = coeff_a;
|
|
step.coeff_b = coeff_b;
|
|
step.gcd = d;
|
|
|
|
if verbose:
|
|
step = steps[0];
|
|
repr = display_table(steps=steps, reverse=True);
|
|
expr = display_sum(step=step);
|
|
print('');
|
|
print('\x1b[1mEuklidescher Algorithmus\x1b[0m');
|
|
print('');
|
|
print(repr);
|
|
print('');
|
|
print('\x1b[1mLösung\x1b[0m');
|
|
print('');
|
|
print(f'a=\x1b[1m{step.a}\x1b[0m; b=\x1b[1m{step.b}\x1b[0m; d = \x1b[1m{step.gcd}\x1b[0m = {expr}.');
|
|
print('');
|
|
|
|
return d, coeff_a, coeff_b;
|