master > master: code - python code umgezogen
This commit is contained in:
4
code/python/requirements
Normal file
4
code/python/requirements
Normal file
@@ -0,0 +1,4 @@
|
||||
pip>=21.3.1
|
||||
argparse>=1.4.0
|
||||
pyyaml>=5.4.1
|
||||
typing>=3.7.4.3
|
||||
0
code/python/src/__init__.py
Normal file
0
code/python/src/__init__.py
Normal file
0
code/python/src/algorithms/__init__.py
Normal file
0
code/python/src/algorithms/__init__.py
Normal file
9
code/python/src/algorithms/exports.py
Normal file
9
code/python/src/algorithms/exports.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.search.exports import *;
|
||||
from src.algorithms.sum.exports import *;
|
||||
96
code/python/src/algorithms/methods.py
Normal file
96
code/python/src/algorithms/methods.py
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import functools;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.setup.display import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASSES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class OneShot(object):
|
||||
state: bool;
|
||||
def __init__(self):
|
||||
self.state = True;
|
||||
|
||||
def setState(self, state: bool):
|
||||
self.state = state;
|
||||
|
||||
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:
|
||||
state1 = nonnestedAlgorithms.state;
|
||||
state2 = nonnestedRecursion.state;
|
||||
state = state1 and state2;
|
||||
if state:
|
||||
# Initialisierung
|
||||
DisplayStartOfAlgorithm(name, **inputs);
|
||||
RestartCounter();
|
||||
# Prechecks
|
||||
if checks and callable(preChecks):
|
||||
preChecks(**inputs);
|
||||
# Ausführung des Algorithmus:
|
||||
nonnestedRecursion.trigger();
|
||||
nonnestedAlgorithms.trigger();
|
||||
outputs = func(*[], **inputs);
|
||||
nonnestedAlgorithms.state = state1;
|
||||
nonnestedRecursion.state = state2;
|
||||
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_) };
|
||||
# Letzte Messages
|
||||
if metrics:
|
||||
DisplayMetrics();
|
||||
DisplayEndOfAlgorithm(**outputsNamed);
|
||||
# Postchecks
|
||||
if checks and callable(postChecks):
|
||||
postChecks(**inputs, **outputsNamed);
|
||||
except Exception as e:
|
||||
nonnestedAlgorithms.state = state1;
|
||||
nonnestedRecursion.state = state2;
|
||||
raise e;
|
||||
return outputs;
|
||||
return func_wrapper;
|
||||
return func_decorator;
|
||||
0
code/python/src/algorithms/search/__init__.py
Normal file
0
code/python/src/algorithms/search/__init__.py
Normal file
66
code/python/src/algorithms/search/binary.py
Normal file
66
code/python/src/algorithms/search/binary.py
Normal file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# 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, **_):
|
||||
if x in L:
|
||||
assert index >= 0, 'Der Algorithmus sollte nicht -1 zurückgeben.';
|
||||
assert L[index] == x, 'Der Algorithmus hat den falschen Index bestimmt.';
|
||||
else:
|
||||
assert index == -1, 'Der Algorithmus sollte -1 zurückgeben.';
|
||||
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.
|
||||
|
||||
Annahme: L sei aufsteigend sortiert.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
if len(L) == 0:
|
||||
logDebug('x nicht in L');
|
||||
return -1;
|
||||
AddToCounter();
|
||||
m = math.floor(len(L)/2);
|
||||
if L[m] == x:
|
||||
logDebug('x in Position m gefunden');
|
||||
return m;
|
||||
elif x < L[m]:
|
||||
logDebug('Suche in linker Hälfte fortsetzen.');
|
||||
index = BinarySearch(L=L[:m], x=x);
|
||||
return index;
|
||||
else: # x > L[m]
|
||||
logDebug('Suche in rechter Hälfte fortsetzen.');
|
||||
index = BinarySearch(L=L[m+1:], x=x);
|
||||
if index >= 0:
|
||||
index += (m + 1); # NOTE: muss Indexwert kompensieren
|
||||
return index;
|
||||
16
code/python/src/algorithms/search/exports.py
Normal file
16
code/python/src/algorithms/search/exports.py
Normal file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.search.sequential import SequentialSearch;
|
||||
from src.algorithms.search.binary import BinarySearch;
|
||||
from src.algorithms.search.interpol import InterpolationSearch;
|
||||
from src.algorithms.search.jump import JumpSearchLinear;
|
||||
from src.algorithms.search.jump import JumpSearchExponentiell;
|
||||
from src.algorithms.search.ith_smallest import FindIthSmallest;
|
||||
from src.algorithms.search.ith_smallest import FindIthSmallestDC;
|
||||
from src.algorithms.search.poison import FindPoison;
|
||||
from src.algorithms.search.poison import FindPoisonFast;
|
||||
72
code/python/src/algorithms/search/interpol.py
Normal file
72
code/python/src/algorithms/search/interpol.py
Normal file
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# 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, **_):
|
||||
if x in L:
|
||||
assert index >= 0, 'Der Algorithmus sollte nicht -1 zurückgeben.';
|
||||
assert L[index] == x, 'Der Algorithmus hat den falschen Index bestimmt.';
|
||||
else:
|
||||
assert index == -1, 'Der Algorithmus sollte -1 zurückgeben.';
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM interpolation
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames='index', 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.
|
||||
|
||||
Annahme: L sei aufsteigend sortiert.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
if not(L[u] <= x and x <= L[v]):
|
||||
logDebug('Element kann sich nicht in der Liste befinden!')
|
||||
return -1;
|
||||
p = getSuchposition(L=L, x=x, u=u, v=v);
|
||||
logDebug('Interpolante von x in (u, v)={uv} ist p = {p}.'.format(uv=(u, v), p=p));
|
||||
if L[p] == x:
|
||||
logDebug('x in Position p gefunden');
|
||||
return p;
|
||||
elif x > L[p]:
|
||||
logDebug('Suche in rechter Hälfte fortsetzen.');
|
||||
return InterpolationSearch(L=L, x=x, u=p+1, v=v);
|
||||
else: # x < L[p]
|
||||
logDebug('Suche in linker Hälfte fortsetzen.');
|
||||
return InterpolationSearch(L=L, x=x, u=u, v=p-1);
|
||||
|
||||
def getSuchposition(L: List[int], x: int, u: int, v: int) -> int:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval.
|
||||
Outputs: Interpolierte Position, um Suchinterval ausgeglichen aufzuteilen.
|
||||
'''
|
||||
AddToCounter();
|
||||
r = (x - L[u])/(L[v]-L[u]);
|
||||
p = math.floor(u + r*(v-u))
|
||||
return p;
|
||||
97
code/python/src/algorithms/search/ith_smallest.py
Normal file
97
code/python/src/algorithms/search/ith_smallest.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.search.sequential import SequentialSearch;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CHECKS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def preChecks(L: List[int], i: int, **_):
|
||||
assert 1 <= i and i <= len(L), 'Der Wert von i muss zw. {lb} und {ub} liegen.'.format(lb = 1, ub = len(L));
|
||||
assert sorted(L) == sorted(list(set(L))), 'Ungültiger Input: L darf keine Duplikate enthalten!';
|
||||
return;
|
||||
|
||||
def postChecks(L: List[int], i: int, value: int, **_):
|
||||
L = sorted(L);
|
||||
assert L[i-1] == value, 'Der Algorithmus hat versagt.';
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM jump search
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames='value', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def FindIthSmallest(L: List[int], i: int) -> int:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen, i = Ordinalzahl
|
||||
|
||||
Annahmen:
|
||||
|
||||
- L enthält keine Duplikate.
|
||||
- L enthält mindestens i Elemente.
|
||||
|
||||
Outputs: Wert des i. kleinste Element in L.
|
||||
Beachte 1.kleinstes <==> Minimum.
|
||||
'''
|
||||
index = 0;
|
||||
minValue = L[0];
|
||||
AddToCounter(len(L));
|
||||
for i_ in range(1, len(L)):
|
||||
if L[i_] < minValue:
|
||||
index = i_;
|
||||
minValue = L[i_];
|
||||
if i == 1:
|
||||
logDebug('Das i. kleinste Element wurde gefunden.');
|
||||
return minValue;
|
||||
else:
|
||||
logDebug('Entfernte Minimum: {value}.'.format(value = minValue));
|
||||
i = i - 1;
|
||||
return FindIthSmallest(L=L[:index] + L[(index+1):], i=i);
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM jump search (D & C)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames='value', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def FindIthSmallestDC(L: List[int], i: int) -> int:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen, i = Ordinalzahl
|
||||
|
||||
Annahmen:
|
||||
|
||||
- L enthält keine Duplikate.
|
||||
- L enthält mindestens i Elemente.
|
||||
|
||||
Outputs: Wert des i. kleinste Element in L.
|
||||
Beachte 1.kleinstes <==> Minimum.
|
||||
'''
|
||||
AddToCounter();
|
||||
p = L[len(L)-1]; # NOTE: Pivotelement kann beliebig gewählt werden
|
||||
Ll = [ x for x in L if x < p ];
|
||||
Lr = [ x for x in L if x > p ];
|
||||
if len(Ll) == i - 1:
|
||||
logDebug('Es gibt i-1 Elemente vor p={p}. ==> i. kleinste Element = p'.format(p=p));
|
||||
return p;
|
||||
elif len(Ll) >= i:
|
||||
logDebug('Es gibt >= i Elemente vor p={p}. ==> Suche in linker Hälfte!'.format(p=p));
|
||||
return FindIthSmallestDC(L=Ll, i=i);
|
||||
else:
|
||||
i = i - (len(Ll) + 1)
|
||||
logDebug('Es gibt < i-1 Elemente vor p={p}. ==> Suche in rechter Hälfte!'.format(p=p));
|
||||
return FindIthSmallestDC(L=Lr, i=i);
|
||||
99
code/python/src/algorithms/search/jump.py
Normal file
99
code/python/src/algorithms/search/jump.py
Normal file
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.search.sequential import SequentialSearch;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CHECKS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def preChecks(L: List[int], **_):
|
||||
assert L == sorted(L), 'Ungültiger Input: L muss aufsteigend sortiert sein!';
|
||||
assert L == sorted(list(set(L))), 'Ungültiger Input: L darf keine Duplikate enthalten!';
|
||||
return;
|
||||
|
||||
def postChecks(L: List[int], x: int, index: int, **_):
|
||||
if x in L:
|
||||
assert index >= 0, 'Der Algorithmus sollte nicht -1 zurückgeben.';
|
||||
assert L[index] == x, 'Der Algorithmus hat den falschen Index bestimmt.';
|
||||
else:
|
||||
assert index == -1, 'Der Algorithmus sollte -1 zurückgeben.';
|
||||
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, m = lineare Sprunggröße.
|
||||
|
||||
Annahmen:
|
||||
- L sei aufsteigend sortiert.
|
||||
- L enthält keine Duplikate.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
i = 0;
|
||||
while i*m < len(L):
|
||||
AddToCounter();
|
||||
offset = i*m;
|
||||
block = L[offset:][:m];
|
||||
elementAfterBlock = block[-1] + 1;
|
||||
if x < elementAfterBlock:
|
||||
logDebug('Element muss sich im Block [{i0}, {i1}) befinden.'.format(i0 = i*m, i1 = (i+1)*m));
|
||||
index = SequentialSearch(L=block, x=x);
|
||||
if index >= 0:
|
||||
index += offset; # NOTE: muss wegen Offset kompensieren
|
||||
return index;
|
||||
logDebug('Element befindet sich nicht im im Block [{i0}, {i1}) befinden.'.format(i0 = i*m, i1 = (i+1)*m));
|
||||
i += 1;
|
||||
return -1;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM jump search - exponentiell
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def JumpSearchExponentiell(L: List[int], x: int) -> int:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen, x = Zahl.
|
||||
|
||||
Annahmen:
|
||||
- L sei aufsteigend sortiert.
|
||||
- L enthält keine Duplikate.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
i0 = 0;
|
||||
i1 = 1;
|
||||
while i0 < len(L):
|
||||
AddToCounter();
|
||||
block = L[i0:i1];
|
||||
elementAfterBlock = block[-1] + 1;
|
||||
if x < elementAfterBlock:
|
||||
logDebug('Element muss sich im Block [{i0}, {i1}) befinden.'.format(i0 = i0, i1 = i1));
|
||||
index = SequentialSearch(L=block, x=x);
|
||||
if index >= 0:
|
||||
index += i0; # NOTE: muss wegen Offset kompensieren
|
||||
return index;
|
||||
logDebug('Element befindet sich nicht im Block [{i0}, {i1}) befinden.'.format(i0 = i0, i1 = i1));
|
||||
i0 = i1;
|
||||
i1 *= 2;
|
||||
return -1;
|
||||
145
code/python/src/algorithms/search/poison.py
Normal file
145
code/python/src/algorithms/search/poison.py
Normal file
@@ -0,0 +1,145 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CHECKS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def preChecks(L: List[bool], **_):
|
||||
assert sum(L) > 0, 'Mindestens ein Getränk muss vergiftet sein!';
|
||||
assert sum(L) == 1, 'Höchstens ein Getränk darf vergiftet sein!';
|
||||
return;
|
||||
|
||||
def postChecks(L: List[bool], index: int, **_):
|
||||
assert L[index] == True, 'Der Algorithmus hat das vergiftete Getränk nicht erfolgreich bestimmt.';
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM find poison
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def FindPoison(L: List[bool]) -> int:
|
||||
'''
|
||||
Inputs: L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist.
|
||||
Annahme: Genau ein Getränk sei vergiftet.
|
||||
Outputs: Der Index des vergifteten Getränks, falls es eines gibt, ansonsten -1.
|
||||
|
||||
NOTE: Zeitkosten hier messen nur die Anzahl der Vorkoster.
|
||||
'''
|
||||
logDebug('Bereite Vorkoster vor');
|
||||
n = len(L);
|
||||
testers = [];
|
||||
for i in range(n):
|
||||
AddToCounter();
|
||||
logDebug('Füge Vorkoster hinzu, der nur Getränk {i} testet.'.format(i=i))
|
||||
testers.append([i]);
|
||||
logDebug('Warte auf Effekte');
|
||||
effects = waitForEffects(L, testers);
|
||||
logDebug('Effekte auswerten, um vergiftete Getränke zu lokalisieren.');
|
||||
poisened = evaluateEffects(testers, effects);
|
||||
if len(poisened) > 0:
|
||||
return poisened[0];
|
||||
return -1;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM find poison fast
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def FindPoisonFast(L: List[bool]) -> List[int]:
|
||||
'''
|
||||
Inputs: L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist.
|
||||
Annahme: Genau ein Getränk sei vergiftet.
|
||||
Outputs: Der Index des vergifteten Getränks, falls es eines gibt, ansonsten -1.
|
||||
|
||||
NOTE: Zeitkosten hier messen nur die Anzahl der Vorkoster.
|
||||
'''
|
||||
logDebug('Bereite Vorkoster vor');
|
||||
n = len(L);
|
||||
p = math.floor(math.log2(n));
|
||||
testers = [];
|
||||
## Für jedes Bit i=0 bis p ...
|
||||
for i in range(p+1):
|
||||
tester0 = [ k for k in range(n) if nthBit(number=k, digit=i) == 0 ];
|
||||
tester1 = [ k for k in range(n) if not (k in tester0) ];
|
||||
# NOTE: tester1 ist virtuell: aus den Effekten auf tester0 und den Annahmen lassen sich die Effekte auf tester0 erschließen.
|
||||
# Darum zählen wir nicht 2 sondern 1 Vorkoster.
|
||||
AddToCounter(1);
|
||||
logDebug('Füge Vorkoster hinzu, der alle Getränke k testet mit {i}. Bit = 0.'.format(i=i))
|
||||
testers.append(tester0);
|
||||
testers.append(tester1);
|
||||
logDebug('Warte auf Effekte');
|
||||
effects = waitForEffects(L, testers);
|
||||
logDebug('Effekte auswerten, um vergiftete Getränke zu lokalisieren.');
|
||||
poisened = evaluateEffects(testers, effects);
|
||||
if len(poisened) > 0:
|
||||
return poisened[0];
|
||||
return -1;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# AUXILIARY METHOD wait for effects, evaluate effects
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def waitForEffects(L: List[bool], testers: List[List[int]]) -> List[int]:
|
||||
'''
|
||||
Inputs:
|
||||
- L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist.
|
||||
- testers = Liste von Vorkostern. Jeder Vorkoster kostet eine 'Teilliste' der Getränke.
|
||||
|
||||
Outputs: effects = eine Liste, die jedem Vorkoster zuordnet, wie viele vergiftete Getränke er konsumiert hat.
|
||||
'''
|
||||
m = len(testers);
|
||||
effects = [];
|
||||
for i in range(m):
|
||||
effect = sum([L[k] for k in testers[i]]);
|
||||
effects.append(effect);
|
||||
return effects;
|
||||
|
||||
def evaluateEffects(testers: List[List[int]], effects: List[int]) -> List[int]:
|
||||
'''
|
||||
Inputs:
|
||||
- testers = Liste von Vorkostern. Jeder Vorkoster kostet eine 'Teilliste' der Getränke.
|
||||
- effects = eine Liste, die jedem Vorkoster zuordnet, wie viele vergiftete Getränke er konsumiert hat.
|
||||
|
||||
Annahmen: Vorkoster wurden so angewiesen, dass es garantiert ist, vergiftete Getränke zu finden, wenn es die gibt.
|
||||
|
||||
Outputs: Liste der Indexes aller vergifteten Getränke.
|
||||
'''
|
||||
## Werte Effekte aus, um Gift zu lokalisieren:
|
||||
search = set([]);
|
||||
## Zuerst die Indexes der Getränke bei allen vergifteten Tester zusammenführen:
|
||||
for i in range(len(testers)):
|
||||
if effects[i] > 0:
|
||||
search = search.union(testers[i]);
|
||||
## jetzt eliminieren wir alle Getränke, die von nicht vergifteten Testern konsumiert wurden:
|
||||
for i in range(len(testers)):
|
||||
if effects[i] == 0:
|
||||
search = search.difference(testers[i]);
|
||||
return list(search);
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# AUXILIARY METHOD n. Bit der binären Darstellung einer Zahl
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def nthBit(number: int, digit: int) -> int:
|
||||
number_binary = bin(number)[2:][::-1];
|
||||
if digit < len(number_binary):
|
||||
return int(number_binary[digit]);
|
||||
return 0;
|
||||
53
code/python/src/algorithms/search/sequential.py
Normal file
53
code/python/src/algorithms/search/sequential.py
Normal file
@@ -0,0 +1,53 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CHECKS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def preChecks(L: List[int], **_):
|
||||
# Keine Checks!
|
||||
return;
|
||||
|
||||
def postChecks(L: List[int], x: int, index: int, **_):
|
||||
if x in L:
|
||||
assert index >= 0, 'Der Algorithmus sollte nicht -1 zurückgeben.';
|
||||
assert L[index] == x, 'Der Algorithmus hat den falschen Index bestimmt.';
|
||||
else:
|
||||
assert index == -1, 'Der Algorithmus sollte -1 zurückgeben.';
|
||||
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.
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
n = len(L);
|
||||
for i in range(n):
|
||||
AddToCounter();
|
||||
if L[i] == x:
|
||||
logDebug('Element in Position {} gefunden.'.format(i));
|
||||
return i;
|
||||
logDebug('Element nicht in Position {}.'.format(i));
|
||||
return -1;
|
||||
0
code/python/src/algorithms/sum/__init__.py
Normal file
0
code/python/src/algorithms/sum/__init__.py
Normal file
9
code/python/src/algorithms/sum/exports.py
Normal file
9
code/python/src/algorithms/sum/exports.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.sum.maxsubsum import MaxSubSum;
|
||||
from src.algorithms.sum.maxsubsum import MaxSubSumDC;
|
||||
179
code/python/src/algorithms/sum/maxsubsum.py
Normal file
179
code/python/src/algorithms/sum/maxsubsum.py
Normal file
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.maths import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CHECKS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def preChecks(L: List[int], **_):
|
||||
assert len(L) > 0, 'Liste darf nicht leer sein.';
|
||||
return;
|
||||
|
||||
def postChecks(L: List[int], **_):
|
||||
# TODO
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM max sub sum
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=('maxSum', 'index_from', 'index_to'), checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def MaxSubSum(L: List[float]) -> Tuple[float, int, int]:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen
|
||||
|
||||
Outputs:
|
||||
- maxSum = Wert der maximalen Summe einer Teilliste aufeinanderfolgender Elemente
|
||||
- u, v = Indexes so dass die Teilliste [L[u], L[u+1], ..., L[v]] die maximale Summe aufweist
|
||||
'''
|
||||
maxSum: float = 0;
|
||||
u: int = 0;
|
||||
v: int = -1;
|
||||
for i in range(len(L)):
|
||||
## Bestimme maximale Teilsumme der linken Rände der Liste ab Index i:
|
||||
maxSum_, _, k = lRandSum(L[i:]);
|
||||
if maxSum_ > maxSum:
|
||||
k += i; # NOTE: muss wegen Offset kompensieren
|
||||
maxSum, u, v = maxSum_, i, k;
|
||||
logDebug('max Teilsumme aktualisiert: Summe L[i] von i={u} .. {v} = {value}'.format(u = u, v = v, value = maxSum));
|
||||
return maxSum, u, v;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM max sub sum (D & C)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme mit D & C)', outputnames=('maxSum', 'index_from', 'index_to'), checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
|
||||
def MaxSubSumDC(L: List[float]) -> Tuple[float, int, int]:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen
|
||||
|
||||
Outputs:
|
||||
- maxSum = Wert der maximalen Summe einer Teilliste aufeinanderfolgender Elemente
|
||||
- u, v = Indexes so dass die Teilliste [L[u], L[u+1], ..., L[v]] die maximale Summe aufweist
|
||||
'''
|
||||
maxSum = 0;
|
||||
u = 0;
|
||||
v = -1;
|
||||
if len(L) == 1:
|
||||
## wenn Liste aus 1 Element besteht, nicht teilen:
|
||||
if L[0] > maxSum:
|
||||
v = 0;
|
||||
maxSum = L[0];
|
||||
else:
|
||||
u = math.ceil(len(L)/2);
|
||||
Ll = L[:u];
|
||||
Lr = L[u:];
|
||||
## berechnet maximale Teilsumme der linken Hälfte:
|
||||
maxSum1, u1, v1 = MaxSubSumDC(L=Ll);
|
||||
## berechnet maximale Teilsumme der rechten Hälfte:
|
||||
maxSum2, u2, v2 = MaxSubSumDC(L=Lr);
|
||||
u2, v2 = u2 + len(Ll), v2 + len(Ll); # offsets kompensieren
|
||||
## berechnet maximale Teilsumme mit Überschneidung zw. den Hälften:
|
||||
maxSum3, u3, v3 = lrRandSum(Ll=Ll, Lr=Lr);
|
||||
## bestimme Maximum der 3 Möglichkeiten:
|
||||
maxSum = max(maxSum1, maxSum2, maxSum3);
|
||||
if maxSum == maxSum1:
|
||||
maxSum, u, v = maxSum1, u1, v1;
|
||||
logDebug('max Teilsumme kommt in linker Partition vor: Summe L[i] von i={i} .. {j} = {value}'.format(L = L, i = u, j = v, value = maxSum));
|
||||
elif maxSum == maxSum3:
|
||||
maxSum, u, v = maxSum3, u3, v3;
|
||||
logDebug('max Teilsumme kommt in Überschneidung vor: Summe L[i] von i={i} .. {j} = {value}'.format(L = L, i = u, j = v, value = maxSum));
|
||||
else: # elif maxSum == maxSum2:
|
||||
maxSum, u, v = maxSum2, u2, v2;
|
||||
logDebug('max Teilsumme kommt in rechter Partition vor: Summe L[i] von i={i} .. {j} = {value}'.format(L = L, i = u, j = v, value = maxSum));
|
||||
return maxSum, u, v;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# AUXILIARY METHODS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def lrRandSum(Ll: List[float], Lr: List[float]) -> Tuple[float, int, int]:
|
||||
'''
|
||||
Bestimmt maximale Teilsumme einer Teiliste einer Liste,
|
||||
wobei die Liste in zwei Intervalle partitioniert ist
|
||||
und die Teilliste beide überschneidet.
|
||||
|
||||
Inputs: Ll, Lr = eine Partition einer Liste von Zahlen in zwei Intervalle
|
||||
Outputs: maxSum, u=0, v
|
||||
'''
|
||||
maxSumL, u, _ = rRandSum(L=Ll);
|
||||
maxSumR, _, v = lRandSum(L=Lr);
|
||||
maxSum = maxSumL + maxSumR;
|
||||
v += len(Ll) # offsets kompensieren
|
||||
return maxSum, u, v;
|
||||
|
||||
def lRandSum(L: List[float]) -> Tuple[float, int, int]:
|
||||
'''
|
||||
Bestimmt maximale Teilsumme aller nicht leeren linken Segmente einer Liste.
|
||||
|
||||
Inputs: L = Liste von Zahlen
|
||||
Outputs: maxSum, u(=0), v
|
||||
'''
|
||||
n = len(L);
|
||||
## berechne kumulative Summen (vorwärts)
|
||||
AddToCounter(n);
|
||||
total = L[0];
|
||||
maxSum = total;
|
||||
u = 0;
|
||||
v = 0;
|
||||
for i in range(1, n):
|
||||
total += L[i];
|
||||
if total > maxSum:
|
||||
v = i;
|
||||
maxSum = total;
|
||||
return maxSum, 0, v;
|
||||
|
||||
def rRandSum(L: List[float]) -> Tuple[float, int, int]:
|
||||
'''
|
||||
Bestimmt maximale Teilsumme aller nicht leeren rechten Segmente einer Liste.
|
||||
|
||||
Inputs: L = Liste von Zahlen
|
||||
Outputs: maxSum, u, v(=len(L)-1)
|
||||
'''
|
||||
n = len(L);
|
||||
## berechne kumulative Summen (rückwärts)
|
||||
AddToCounter(n);
|
||||
total = L[n-1];
|
||||
maxSum = total;
|
||||
u = n-1;
|
||||
v = n-1;
|
||||
for i in range(0, n-1)[::-1]:
|
||||
total += L[i];
|
||||
if total > maxSum:
|
||||
u = i;
|
||||
maxSum = total;
|
||||
return maxSum, u, v;
|
||||
|
||||
# Sei N ∈ ℕ⁺
|
||||
# Sei p so, dass 2^p ≤ N < 2^{p+1},
|
||||
# Also p = floor(log₂(N)).
|
||||
# Setze
|
||||
# B(i,d) := {k < N | bit(k, i) = d}
|
||||
# für i ∈ {0, 1, ..., p-1}
|
||||
# und setze
|
||||
# 𝒜 = {B(i,d) : i ∈ {0, 1, ..., p-1}, d ∈ {0,1}}.
|
||||
# Seien k1, k2 ∈ N mit k1 ≠ k2.
|
||||
# Dann existiert i ∈ {0, 1, ..., p-1},
|
||||
# so dass
|
||||
# d := bit(k1, i) ≠ bit(k2, i).
|
||||
# Also
|
||||
# k1 ∈ B(i, d) ∌ k2.
|
||||
# Darum erfüllt 𝒜 die erwünschte Eigenschaft.
|
||||
# Es gilt
|
||||
# |𝒜| = 2p = 2·floor(log₂(N)) ∈ O(log(N)).
|
||||
0
code/python/src/core/__init__.py
Normal file
0
code/python/src/core/__init__.py
Normal file
60
code/python/src/core/config.py
Normal file
60
code/python/src/core/config.py
Normal file
@@ -0,0 +1,60 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.typing import *;
|
||||
from src.local.config import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD read config file
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def ReadConfigFile(path: str) -> dict:
|
||||
with open(path, 'r') as fp:
|
||||
spec = load(fp, Loader=FullLoader);
|
||||
assert isinstance(spec, dict), 'Die Configdatei muss eines Dictionary-Typs sein';
|
||||
return spec;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD extract attribut from dictionary/list
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def GetAttribute(
|
||||
obj: Any,
|
||||
*keys: Union[str, int, List[Union[str, int]]],
|
||||
expectedtype: Union[Type, Tuple[Type]] = Any,
|
||||
default: Any = None
|
||||
) -> Any:
|
||||
if len(keys) == 0:
|
||||
return obj;
|
||||
nextkey = keys[0];
|
||||
nextkey = nextkey if isinstance(nextkey, list) else [ nextkey ];
|
||||
try:
|
||||
for key in nextkey:
|
||||
if isinstance(key, str) and isinstance(obj, dict) and key in obj:
|
||||
value = obj[key];
|
||||
if len(keys) <= 1:
|
||||
return value if isinstance(value, expectedtype) else default;
|
||||
else:
|
||||
return GetAttribute(obj[key], *keys[1:], expectedtype=expectedtype, default=default);
|
||||
elif isinstance(key, int) and isinstance(obj, (list,tuple)) and key < len(obj):
|
||||
value = obj[key];
|
||||
if len(keys) <= 1:
|
||||
return value if isinstance(value, expectedtype) else default;
|
||||
else:
|
||||
return GetAttribute(obj[key], *keys[1:], expectedtype=expectedtype, default=default);
|
||||
except:
|
||||
pass;
|
||||
if len(keys) <= 1:
|
||||
return default;
|
||||
path = ' -> '.join([ str(key) for key in keys ]);
|
||||
raise Exception('Konnte \033[1m{}\033[0m im Objekt nicht finden!'.format(path));
|
||||
130
code/python/src/core/log.py
Normal file
130
code/python/src/core/log.py
Normal file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.io import *;
|
||||
from src.local.misc import *;
|
||||
from src.local.system import *;
|
||||
from src.local.typing import *;
|
||||
|
||||
from datetime import timedelta;
|
||||
|
||||
from src.core.metrics import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
_logging_prefix: str = '';
|
||||
_quietmode: bool = False;
|
||||
_debugmode: bool = False;
|
||||
_ctr: Counter = Counter();
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHOD get/set quiet mode, logging depth, timer
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def GetQuietMode() -> bool:
|
||||
return _quietmode;
|
||||
|
||||
def SetQuietMode(mode: bool):
|
||||
global _quietmode;
|
||||
_quietmode = mode;
|
||||
return;
|
||||
|
||||
def GetDebugMode() -> bool:
|
||||
return _debugmode;
|
||||
|
||||
def SetDebugMode(mode: bool):
|
||||
global _debugmode;
|
||||
_debugmode = mode;
|
||||
return;
|
||||
|
||||
def RestartCounter():
|
||||
global _ctr;
|
||||
_ctr.reset();
|
||||
return;
|
||||
|
||||
def AddToCounter(n: int = 1):
|
||||
global _ctr;
|
||||
_ctr.add(n);
|
||||
return;
|
||||
|
||||
def NumberOfSteps() -> int:
|
||||
return _ctr.numberOfStep;
|
||||
|
||||
def TimeElapsed() -> timedelta:
|
||||
global _ctr;
|
||||
_ctr.stop();
|
||||
return _ctr.elapsedTime;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# Logging
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def logGeneric(tag: str, *lines: Any, file: io.TextIOWrapper, force: bool = False, tag_all: bool = True):
|
||||
if not force and _quietmode:
|
||||
return;
|
||||
tag = '' if tag == '' else tag + ' ';
|
||||
file = file or sys.stdout;
|
||||
for line in lines:
|
||||
print('{}{}{}'.format('', tag, line), file=file);
|
||||
if not tag_all:
|
||||
tag = '';
|
||||
return;
|
||||
|
||||
def logPlain(*lines: Any, force: bool = False, file: Any = None):
|
||||
logGeneric('', *lines, force=force, file=file or sys.stdout);
|
||||
|
||||
def logInfo(*lines: Any, force: bool = False, tag_all: bool = True, file: Any = None):
|
||||
logGeneric('[\033[94;1mINFO\033[0m]', *lines, force=force, tag_all=tag_all, file=file or sys.stdout);
|
||||
|
||||
def logDebug(*lines: Any, force: bool = False, tag_all: bool = True, file: Any = None):
|
||||
if not _debugmode:
|
||||
return;
|
||||
logGeneric('\033[2m[\033[96;1mDEBUG\033[0m\033[2m]\033[0m',
|
||||
*[ '\033[2m{}\033[0m'.format(line) for line in lines ],
|
||||
force=force, tag_all=tag_all, file=file or sys.stdout
|
||||
);
|
||||
|
||||
def logWarn(*lines: Any, force: bool = False, tag_all: bool = False, file: Any = None):
|
||||
logGeneric('[\033[93;1mWARNING\033[0m]', *lines, force=force, tag_all=tag_all, file=file or sys.stdout);
|
||||
|
||||
def logError(*lines: Any, force: bool = False, tag_all: bool = False, file: Any = None):
|
||||
logGeneric('[\033[91;1mERROR\033[0m]', *lines, force=force, tag_all=tag_all, file=file or sys.stderr);
|
||||
|
||||
def logFatal(*lines: Any, force: bool = False, tag_all: bool = False, file: Any = None):
|
||||
logGeneric('[\033[91;1mFATAL\033[0m]', *lines, force=force, tag_all=tag_all, file=file or sys.stderr);
|
||||
exit(1);
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# User Input
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def askUserInput(message: str, expectedformat: Callable) -> Union[str, None]:
|
||||
answer = None;
|
||||
while True:
|
||||
try:
|
||||
answer = input('{}{}'.format(_logging_prefix, message));
|
||||
## Meta+C erkennen:
|
||||
except KeyboardInterrupt:
|
||||
logPlain('');
|
||||
return None;
|
||||
## Meta+D erkennen:
|
||||
except EOFError:
|
||||
logPlain('');
|
||||
return None;
|
||||
except:
|
||||
continue;
|
||||
if expectedformat(answer):
|
||||
break;
|
||||
return answer;
|
||||
|
||||
def askConfirmation(message: str, default: bool = False) -> bool:
|
||||
answer = askUserInput(message, lambda x: not not re.match(r'^(y|yes|j|ja|n|no|nein)$', x));
|
||||
if isinstance(answer, str):
|
||||
return True if re.match(r'^(y|yes|j|ja)$', answer) else False;
|
||||
return default;
|
||||
53
code/python/src/core/metrics.py
Normal file
53
code/python/src/core/metrics.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# !/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from datetime import datetime;
|
||||
from datetime import timedelta;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASS counter
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class Counter(object):
|
||||
_nr_steps: int;
|
||||
_timeelapsed: timedelta;
|
||||
_timecurrent: datetime;
|
||||
|
||||
def __init__(self):
|
||||
self.reset();
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self._nr_steps);
|
||||
|
||||
@property
|
||||
def numberOfStep(self) -> int:
|
||||
return self._nr_steps;
|
||||
|
||||
@property
|
||||
def elapsedTime(self) -> timedelta:
|
||||
return self._timeelapsed;
|
||||
def start(self):
|
||||
self._timecurrent = datetime.now();
|
||||
return self;
|
||||
|
||||
def stop(self):
|
||||
t0 = self._timecurrent;
|
||||
t1 = datetime.now();
|
||||
self._timecurrent = t1;
|
||||
self._timeelapsed += (t1 - t0);
|
||||
return self;
|
||||
|
||||
def add(self, n: int = 1):
|
||||
self._nr_steps += n;
|
||||
return self;
|
||||
|
||||
def reset(self):
|
||||
t = datetime.now();
|
||||
self._timeelapsed = t - t;
|
||||
self._nr_steps = 0;
|
||||
self._timecurrent = t;
|
||||
return self;
|
||||
0
code/python/src/local/__init__.py
Normal file
0
code/python/src/local/__init__.py
Normal file
12
code/python/src/local/config.py
Normal file
12
code/python/src/local/config.py
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import json;
|
||||
from yaml import add_constructor;
|
||||
from yaml import load;
|
||||
from yaml import Loader;
|
||||
from yaml import FullLoader;
|
||||
10
code/python/src/local/io.py
Normal file
10
code/python/src/local/io.py
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import io;
|
||||
import getpass;
|
||||
import argparse;
|
||||
9
code/python/src/local/maths.py
Normal file
9
code/python/src/local/maths.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import math;
|
||||
import random;
|
||||
9
code/python/src/local/misc.py
Normal file
9
code/python/src/local/misc.py
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import re;
|
||||
from textwrap import dedent;
|
||||
12
code/python/src/local/system.py
Normal file
12
code/python/src/local/system.py
Normal file
@@ -0,0 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import os;
|
||||
import sys;
|
||||
|
||||
import platform;
|
||||
import shutil;
|
||||
19
code/python/src/local/typing.py
Normal file
19
code/python/src/local/typing.py
Normal file
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from types import TracebackType;
|
||||
|
||||
from typing import Any;
|
||||
from typing import Callable;
|
||||
from typing import Dict;
|
||||
from typing import Generator;
|
||||
from typing import Generic;
|
||||
from typing import List;
|
||||
from typing import Tuple;
|
||||
from typing import Type;
|
||||
from typing import TypeVar;
|
||||
from typing import Union;
|
||||
97
code/python/src/main.py
Normal file
97
code/python/src/main.py
Normal file
@@ -0,0 +1,97 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import os;
|
||||
import sys;
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.abspath(__file__), '..', '..')));
|
||||
os.chdir(os.path.abspath(os.path.join(os.path.abspath(__file__), '..', '..', '..', '..')));
|
||||
|
||||
from src.core.log import *;
|
||||
from src.core.config import *;
|
||||
from src.setup.display import *;
|
||||
from src.setup.cli import *;
|
||||
from src.algorithms.exports import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
PATH_TO_CONFIG: str = 'code/config.yml';
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# MAIN PROCESS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def enter(quiet: bool, debug: bool, mode: str, path: Any, **_):
|
||||
SetQuietMode(quiet);
|
||||
SetDebugMode(debug);
|
||||
configpath = path if isinstance(path, str) else PATH_TO_CONFIG;
|
||||
if mode in 'run':
|
||||
LoopThroughCases(path=configpath);
|
||||
else:
|
||||
DisplayHelpMessage();
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# SECONDARY PROCESSES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def LoopThroughCases(path: str):
|
||||
'''
|
||||
Durchlauf aller Testfälle.
|
||||
'''
|
||||
config = ReadConfigFile(path);
|
||||
cases = GetAttribute(config, 'parts', 'cases', expectedtype=list, default=[]);
|
||||
for caseindex, case in enumerate(cases):
|
||||
command = GetAttribute(case, 'command', expectedtype=str, default='');
|
||||
descr = GetAttribute(case, 'description', expectedtype=str, default='');
|
||||
inputs = GetAttribute(case, 'inputs', expectedtype=dict, default={});
|
||||
|
||||
DisplayStartOfCase(caseindex, descr);
|
||||
|
||||
try:
|
||||
if command == 'algorithm-sum-maxsub':
|
||||
MaxSubSum(L=inputs['L']);
|
||||
elif command == 'algorithm-sum-maxsub-dc':
|
||||
MaxSubSumDC(L=inputs['L']);
|
||||
elif command == 'algorithm-search-sequential':
|
||||
SequentialSearch(L=inputs['L'], x=inputs['x']);
|
||||
elif command == 'algorithm-search-binary':
|
||||
BinarySearch(L=inputs['L'], x=inputs['x']);
|
||||
elif command == 'algorithm-search-interpolation':
|
||||
InterpolationSearch(L=inputs['L'], x=inputs['x'], u=0, v=len(inputs['L'])-1);
|
||||
elif command == 'algorithm-search-jump':
|
||||
JumpSearchLinear(L=inputs['L'], x=inputs['x'], m=inputs['m']);
|
||||
elif command == 'algorithm-search-jump-exp':
|
||||
JumpSearchExponentiell(L=inputs['L'], x=inputs['x']);
|
||||
elif command == 'algorithm-search-ith-element':
|
||||
FindIthSmallest(L=inputs['L'], i=inputs['i']);
|
||||
elif command == 'algorithm-search-ith-element-dc':
|
||||
FindIthSmallestDC(L=inputs['L'], i=inputs['i']);
|
||||
elif command == 'algorithm-search-poison':
|
||||
FindPoison(L=inputs['L']);
|
||||
elif command == 'algorithm-search-poison-fast':
|
||||
FindPoisonFast(L=inputs['L']);
|
||||
else:
|
||||
raise ValueError('Command \033[1m{}\033[0m nicht erkannt'.format(command));
|
||||
except Exception as e:
|
||||
logError(e);
|
||||
DisplayEndOfCase();
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXECUTE CODE
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.tracebacklimit = 0;
|
||||
try:
|
||||
args = GetArgumentsFromCli(sys.argv[1:]);
|
||||
except:
|
||||
exit(1);
|
||||
enter(quiet=args.quiet, debug=args.debug, mode=args.mode[0], path=args.path);
|
||||
0
code/python/src/setup/__init__.py
Normal file
0
code/python/src/setup/__init__.py
Normal file
41
code/python/src/setup/cli.py
Normal file
41
code/python/src/setup/cli.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
parser = None;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def GetArgumentParser() -> argparse.ArgumentParser:
|
||||
global parser;
|
||||
if not isinstance(parser, argparse.ArgumentParser):
|
||||
parser = argparse.ArgumentParser(
|
||||
prog='code/main.py',
|
||||
description=dedent('''
|
||||
\033[93;1mBeschreibung:\033[0m
|
||||
\033[93;2mEin Programm, das verschiedene Algorithmen aus dem Kurs AlgoDat I testet.\033[0m
|
||||
'''),
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
);
|
||||
parser.add_argument('mode', nargs=1, choices=['run'], help='run = Führt alle Testfälle in der config.yml Datei durch.');
|
||||
parser.add_argument('--path', nargs=1, type=str, help='Pfad zur alternativen Configdatei.');
|
||||
parser.add_argument('--debug', action='store_true', help='Debugging Messages stummschalten.')
|
||||
parser.add_argument('-q', '--quiet', action='store_true', help='Alle console-messages bis auf Errors stummschalten.')
|
||||
return parser;
|
||||
|
||||
def GetArgumentsFromCli(cli_args: List[str]) -> argparse.Namespace:
|
||||
parser = GetArgumentParser();
|
||||
return parser.parse_args(cli_args);
|
||||
80
code/python/src/setup/display.py
Normal file
80
code/python/src/setup/display.py
Normal file
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.setup.cli import GetArgumentParser;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS display help
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def DisplayHelpMessage():
|
||||
parser = GetArgumentParser();
|
||||
parser.print_help();
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS display case
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def DisplayStartOfCase(index: int, descr: Any):
|
||||
DisplayBar(80);
|
||||
if not isinstance(descr, str) or descr == '':
|
||||
logPlain('\033[92;1mCASE {index}\033[0m.'.format(index=index));
|
||||
else:
|
||||
logPlain('\033[92;1mCASE {index}\033[0m (\033[1;2m{descr}\033[0m).'.format(index=index, descr=descr));
|
||||
return;
|
||||
|
||||
def DisplayEndOfCase():
|
||||
DisplayBar(80);
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS display value
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def RepresentValue(value: Any) -> Any:
|
||||
if value is None or isinstance(value, (str, bool, int, float)):
|
||||
return value;
|
||||
elif isinstance(value, list):
|
||||
if len(value) > 10:
|
||||
value = value[:3] + [ '...' ] + value[-2:];
|
||||
# return '[{}, ..., {}]'.format(', '.join(value[:3]), ', '.join(value[-2:])
|
||||
return value;
|
||||
return value;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS display algorithm start/end
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def DisplayStartOfAlgorithm(name: str, *_: Any, **inputs: Any):
|
||||
logPlain('Ausführung vom Algorithmus: \033[92;1m{}\033[0m'.format(name));
|
||||
logPlain('INPUTS');
|
||||
for varname, value in inputs.items():
|
||||
logPlain(' - {} = {}'.format(varname, RepresentValue(value)))
|
||||
return;
|
||||
|
||||
def DisplayEndOfAlgorithm(*_: Any, **outputs: Any):
|
||||
logPlain('OUTPUTS:')
|
||||
for varname, value in outputs.items():
|
||||
logPlain(' - {} = {}'.format(varname, RepresentValue(value)))
|
||||
return;
|
||||
|
||||
def DisplayMetrics():
|
||||
logPlain('Dauer der Ausführung: t = \033[1m{}\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;
|
||||
Reference in New Issue
Block a user