Compare commits

...

4 Commits

8 changed files with 188 additions and 57 deletions

View File

@ -41,8 +41,8 @@ Python version 3.x.x (idealerweise zumindest 3.9.5) plus folgende Module:
Diese lassen sich mittels
```bash
python3 -m pip install {name des Moduls} # linux, osx
py -3 -m pip install {name des Moduls} # Windows
python3 -m pip install {name des Moduls}; # linux, osx
py -3 -m pip install {name des Moduls}; # Windows
```
installieren.
Man kann auch die Version mittels etwa `{name}==1.2.3` oder `{name}>=1.2.3` spezifizieren.
@ -61,3 +61,5 @@ chmod +x run.sh; # nur einmalig nötig
./run.sh
```
aus.
Der Befehl `[python3 | py -3] code/main.py -h` zeigt die Gebrauchsanleitung an.

View File

@ -0,0 +1,90 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import functools;
from code.core.log import *;
from code.display.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CLASSES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class OneShot(object):
state: bool;
def __init__(self):
self.state = True;
def reload(self):
self.state = True;
def trigger(self):
self.state = False;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# DECORATORS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## Trigger, der das fancy Zeug bei verschachtelten Algorithmen verhindert
nonnestedAlgorithms = OneShot();
def algorithmInfos(
name: str,
checks: bool = True,
metrics: bool = None,
outputnames: Union[str, Tuple[str]] = 'result',
preChecks: Any = None,
postChecks: Any = None
):
'''
Decorator für Algorthmen, der Folgendes macht:
- Zeigt vorm Start Console-Messages mit Namen des Algorithmus + Inputs.
- Zeit am Ende optional Metriken (bspw. Zeitkosten).
- Zeigt am Ende Console-Messages von Output/s.
- Prüft optional vor und nach Ausführung des Algorithmus, dass die Inputs/Outputs stimmen.
Bei rekursiven Definitionen werden die o. s. Punkte nur bei dem äußersten Aufruf gemacht.
'''
def func_decorator(func):
## Trigger, der das fancy Zeug bei verschachtelten Aufrufen verhindert
nonnestedRecursion = OneShot();
@functools.wraps(func)
def func_wrapper(**inputs):
try:
state = nonnestedRecursion.state and nonnestedAlgorithms.state;
if state:
# Initialisierung
DisplayStartOfAlgorithm(name.title(), **inputs);
RestartCounter();
# Prechecks
if checks and callable(preChecks):
preChecks(**inputs);
# Ausführung des Algorithmus:
nonnestedRecursion.trigger();
nonnestedAlgorithms.trigger();
outputs = func(*[], **inputs);
nonnestedAlgorithms.reload();
nonnestedRecursion.reload();
if state:
# benenne Outputs:
outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]);
outputnames_ = outputnames if isinstance(outputnames, tuple) else tuple([outputnames]);
outputsNamed = { outputnames_[k]: value for k, value in enumerate(outputs_) };
# Postchecks
if checks and callable(postChecks):
postChecks(**inputs, **outputsNamed);
# Letzte Messages
if metrics:
DisplayMetrics();
DisplayEndOfAlgorithm(**outputsNamed);
except Exception as e:
_switch.reload();
raise e;
return outputs;
return func_wrapper;
return func_decorator;

View File

@ -9,6 +9,7 @@ from local.maths import *;
from local.typing import *;
from code.core.log import *;
from code.algorithms.methods import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES/CONSTANTS
@ -16,10 +17,24 @@ from code.core.log import *;
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CHECKS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def preChecks(L: List[int], **_):
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
return;
def postChecks(L: List[int], x: int, index: int, **_):
value = L[index] if index >= 0 else None;
assert value == x, 'Der Algorithmus hat versagt.';
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM binary search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Binärsuchalgorithmus', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def BinarySearch(L: List[int], x: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl.
@ -36,9 +51,9 @@ def BinarySearch(L: List[int], x: int) -> int:
return m;
elif x < L[m]:
logDebug('Suche in L[0], L[1], ..., L[m] fortsetzen, m = {}.'.format(m));
index = BinarySearch(L[:m], x);
index = BinarySearch(L=L[:m], x=x);
return index;
else: # x > L[m]
logDebug('Suche in L[m+1], L[m+2], ..., L[len(L)-1] fortsetzen, m = {}.'.format(m));
index = BinarySearch(L[m+1:], x);
index = BinarySearch(L=L[m+1:], x=x);
return (m + 1) + index; # NOTE: muss Indexwert kompensieren

View File

@ -9,6 +9,7 @@ from local.maths import *;
from local.typing import *;
from code.core.log import *;
from code.algorithms.methods import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES/CONSTANTS
@ -16,10 +17,24 @@ from code.core.log import *;
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CHECKS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def preChecks(L: List[int], **_):
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
return;
def postChecks(L: List[int], x: int, p: int, **_):
value = L[p] if p >= 0 else None;
assert value == x, 'Der Algorithmus hat versagt.';
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM interpolation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames='p', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def InterpolationSearch(L: List[int], x: int, u: int, v: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval.

View File

@ -10,6 +10,7 @@ from local.typing import *;
from code.core.log import *;
from code.algorithms.search.sequential import SequentialSearch;
from code.algorithms.methods import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES/CONSTANTS
@ -17,10 +18,25 @@ from code.algorithms.search.sequential import SequentialSearch;
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CHECKS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def preChecks(L: List[int], **_):
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
assert L == list(sorted(set(L))), 'Ungültiger Input: L darf keine Duplikate enthalten!';
return;
def postChecks(L: List[int], x: int, index: int, **_):
value = L[index] if index >= 0 else None;
assert value == x, 'Der Algorithmus hat versagt.';
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM jump search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval.
@ -37,7 +53,7 @@ def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
elementAfterBlock = block[-1] + 1;
if x < elementAfterBlock:
logDebug('Element muss sich im Block {} befinden.'.format(i));
index = SequentialSearch(block, x);
index = SequentialSearch(L=block, x=x);
return offset + index; # NOTE: muss wegen Offset kompensieren
logDebug('Element befindet sich nicht im Block {}.'.format(i));
i += 1;

View File

@ -9,6 +9,7 @@ from local.maths import *;
from local.typing import *;
from code.core.log import *;
from code.algorithms.methods import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES/CONSTANTS
@ -16,10 +17,24 @@ from code.core.log import *;
#
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CHECKS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def preChecks(L: List[int], **_):
# Keine Checks!
return;
def postChecks(L: List[int], x: int, index: int, **_):
value = L[index] if index >= 0 else None;
assert value == x, 'Der Algorithmus hat versagt.';
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM sequential search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def SequentialSearch(L: List[int], x: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl.

View File

@ -22,21 +22,30 @@ def DisplayCase(name: Any):
# METHODS display algorithm start/end
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def DisplayStartOfAlgorithm(name: str, **inputs: Any):
logInfo('Ausführung vom Algorithmus: \033[92;1m{}\033[0m'.format(name))
logInfo('INPUTS');
def DisplayStartOfAlgorithm(name: str, *_: Any, **inputs: Any):
DisplayBar(80);
logPlain('Ausführung vom Algorithmus: \033[92;1m{}\033[0m'.format(name));
logPlain('INPUTS');
for varname, value in inputs.items():
logPlain(' - {} = {}'.format(varname, value))
return;
def DisplayEndOfAlgorithm(**outputs: Any):
logInfo('OUTPUTS:')
def DisplayEndOfAlgorithm(*_: Any, **outputs: Any):
logPlain('OUTPUTS:')
for varname, value in outputs.items():
logPlain(' - {} = {}'.format(varname, value))
DisplayMetrics()
DisplayBar(80);
return;
def DisplayMetrics():
logInfo('Dauer der Ausführung: t = \033[2m{}\033[0m'.format(TimeElapsed()))
logInfo('Anzahl der Schritte: T(n) = \033[1m{}\033[0m'.format(NumberOfSteps()))
logPlain('Dauer der Ausführung: t = \033[2m{}\033[0m'.format(TimeElapsed()));
logPlain('Anzahl der Schritte: T(n) = \033[1m{}\033[0m'.format(NumberOfSteps()));
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS Verschiedenes
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def DisplayBar(n: int = 80):
logPlain('+{}+'.format('-'*n));
return;

View File

@ -51,51 +51,20 @@ def LoopThroughCases(path: str):
command = GetAttribute(case, 'command', expectedtype=str, default='');
inputs = GetAttribute(case, 'inputs', expectedtype=dict, default={});
checks = GetAttribute(case, 'check', expectedtype=bool, default=True);
RestartCounter();
try:
if command == 'algorithm-search-sequential':
L, x = inputs['L'], inputs['x'];
DisplayStartOfAlgorithm('Sequenziellsuche', L=L, x=x);
p = SequentialSearch(L=L, x=x);
value = L[p] if p >= 0 else None;
if checks:
assert value == x, 'Der Algorithmus hat versagt.';
DisplayEndOfAlgorithm(p = p);
SequentialSearch(L=inputs['L'], x=inputs['x']);
elif command == 'algorithm-search-binary':
L, x = inputs['L'], inputs['x'];
DisplayStartOfAlgorithm('Binärsuche', L=L, x=x);
if checks:
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
p = BinarySearch(L=L, x=x);
value = L[p] if p >= 0 else None;
if checks:
assert value == x, 'Der Algorithmus hat versagt.';
DisplayEndOfAlgorithm(p = p);
BinarySearch(L=inputs['L'], x=inputs['x']);
elif command == 'algorithm-search-interpolation':
L, x = inputs['L'], inputs['x'];
u, v = 0, len(L)-1;
DisplayStartOfAlgorithm('Interpolationssuche', L=L, x=x, u=u, v=v);
if checks:
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
p = InterpolationSearch(L=L, x=x, u=u, v=v);
value = L[p] if p >= 0 else None;
if checks:
assert value == x, 'Der Algorithmus hat versagt.';
DisplayEndOfAlgorithm(p = p);
InterpolationSearch(L=inputs['L'], x=inputs['x'], u=0, v=len(inputs['L'])-1);
elif command == 'algorithm-search-jump':
L, x, m = inputs['L'], inputs['x'], inputs['m'];
DisplayStartOfAlgorithm('SprungSuche', L=L, x=x, m=m);
if checks:
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
assert L == list(sorted(set(L))), 'Ungültiger Input: L darf keine Duplikate enthalten!';
p = JumpSearchLinear(L=L, x=x, m=m);
value = L[p] if p >= 0 else None;
if checks:
assert value == x, 'Der Algorithmus hat versagt.';
DisplayEndOfAlgorithm(p = p);
JumpSearchLinear(L=inputs['L'], x=inputs['x'], m=inputs['m']);
else:
raise ValueError('Command \033[1m{}\033[0m nicht erkannt'.format(command));
except Exception as e:
logError(e);
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~