From f1200dfc25784fab5822cc4d8cc46a033effa308 Mon Sep 17 00:00:00 2001 From: raj_mathe Date: Mon, 20 Jun 2022 16:46:35 +0200 Subject: [PATCH] woche12 > master: code py - euklid alg implementiert --- .../src/algorithms/euklid/algorithms.py | 71 ++++++++++++++++++- code/python/src/algorithms/euklid/display.py | 56 +++++++++++++++ .../src/endpoints/ep_algorithm_euklid.py | 4 +- .../models/{euklid.py => euklid}/__init__.py | 3 +- code/python/src/models/euklid/logging.py | 30 ++++++++ 5 files changed, 158 insertions(+), 6 deletions(-) rename code/python/src/models/{euklid.py => euklid}/__init__.py (90%) create mode 100644 code/python/src/models/euklid/logging.py diff --git a/code/python/src/algorithms/euklid/algorithms.py b/code/python/src/algorithms/euklid/algorithms.py index bf3e1cc..d853809 100644 --- a/code/python/src/algorithms/euklid/algorithms.py +++ b/code/python/src/algorithms/euklid/algorithms.py @@ -10,7 +10,7 @@ from src.thirdparty.maths import *; from models.generated.config import *; from src.core.utils import *; -# from src.models.euklid import *; +from src.models.euklid import *; from src.algorithms.euklid.display import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -29,5 +29,70 @@ def euklidean_algorithm( a: int, b: int, verbose: bool = False, -): - return; +) -> 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; diff --git a/code/python/src/algorithms/euklid/display.py b/code/python/src/algorithms/euklid/display.py index e69de29..59eab86 100644 --- a/code/python/src/algorithms/euklid/display.py +++ b/code/python/src/algorithms/euklid/display.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.thirdparty.code import *; +from src.thirdparty.maths import *; +from src.thirdparty.types import *; + +from src.models.euklid import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'display_table', + 'display_sum', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD display table +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def display_table( + steps: List[Step], + reverse: bool = False, +) -> str: + if reverse: + steps = steps[::-1]; + table = pd.DataFrame({ + 'a': [step.a for step in steps], + 'b': [step.b for step in steps], + 'div': ['-' if step.b == 0 else step.div for step in steps], + 'gcd': [step.gcd for step in steps], + 'expr': [f'= {display_sum(step=step)}' for step in steps], + }) \ + .reset_index(drop=True); + # benutze pandas-Dataframe + tabulate, um schöner darzustellen: + repr = tabulate( + table, + headers=['a', 'b', 'floor(a/b)', 'gcd(a,b)', 'gcd(a,b)=x·a + y·b'], + showindex=False, + colalign=('right', 'right', 'right', 'center', 'left'), + tablefmt='simple' + ); + return repr; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# METHOD display table +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +def display_sum(step: Step) -> str: + return f'\x1b[1m{step.coeff_a}\x1b[0m·a + \x1b[1m{step.coeff_b}\x1b[0m·b' ; diff --git a/code/python/src/endpoints/ep_algorithm_euklid.py b/code/python/src/endpoints/ep_algorithm_euklid.py index 7b19904..79aece4 100644 --- a/code/python/src/endpoints/ep_algorithm_euklid.py +++ b/code/python/src/endpoints/ep_algorithm_euklid.py @@ -27,8 +27,8 @@ __all__ = [ @run_safely() def endpoint_euklid(command: CommandEuklid) -> Result[CallResult, CallError]: result = euklidean_algorithm( - a = command.numbers[0], - b = command.numbers[1], + a = command.numbers[0].__root__, + b = command.numbers[1].__root__, verbose = config.OPTIONS.tsp.verbose, ); return Ok(CallResult(action_taken=True, message=result)); diff --git a/code/python/src/models/euklid.py/__init__.py b/code/python/src/models/euklid/__init__.py similarity index 90% rename from code/python/src/models/euklid.py/__init__.py rename to code/python/src/models/euklid/__init__.py index cee1f46..fd2630f 100644 --- a/code/python/src/models/euklid.py/__init__.py +++ b/code/python/src/models/euklid/__init__.py @@ -5,11 +5,12 @@ # IMPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# from src.models.euklid. import *; +from src.models.euklid.logging import *; # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # EXPORTS # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ __all__ = [ + 'Step', ]; diff --git a/code/python/src/models/euklid/logging.py b/code/python/src/models/euklid/logging.py new file mode 100644 index 0000000..086b26c --- /dev/null +++ b/code/python/src/models/euklid/logging.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# IMPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +from src.thirdparty.types import *; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# EXPORTS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +__all__ = [ + 'Step', +]; + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CLASS Step +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +@dataclass +class Step(): + a: int = field(); + b: int = field(); + gcd: int = field(); + div: int = field(); + rem: int = field(); + coeff_a: int = field(); + coeff_b: int = field();