Compare commits

...

6 Commits

28 changed files with 467 additions and 199 deletions

8
.gitignore vendored
View File

@ -28,10 +28,10 @@
!/code/python/**/*.py
!/code/golang/**/*.go
!/code/golang/go.mod
!/code/golang/assets/HELP
!/code/golang/assets/VERSION
!/code/golang/assets/LOGO
!/code/golang/assets/config.yml
!/code/*/assets/VERSION
!/code/*/assets/LOGO
!/code/*/assets/config.yml
!/code/*/README.md
!/code/*/requirements
!/code/config.yml
## nicht synchronisieren:

101
README.md
View File

@ -27,97 +27,10 @@ In diesem Repository findet man:
## Code ##
Im Unterordner [`code`](./code) kann man Codeprojekte in Python und Golang finden, in denen verschiedene Algorithmen implementiert werden
(siehe insbes. [`code/python/src/algorithms`](./code/python//src/algorithms)
und [`code/golang/internal/algorithms`](./code/golang/internal/algorithms)).
Gerne kann man den Code benutzen, in einem eigenen Repository verändern, und mit den im Kurs präsentierten Algorithmen **herumexperimentieren**.
**HINWEIS:** _Bei meiner Implementierung kann es zu leichten Abweichungen kommen. Bitte **stets** an dem Material im VL-Skript sich orientieren. Der Hauptzweck der Code-Projekte besteht darin, dass Wissbegierige die Algorithmen konkret ausprobieren können. Alle theoretischen Aspekte werden jedoch im Skript und in den Übungen ausführlicher erklärt._
### Systemvoraussetzungen ###
#### Bashscripts ####
Im Ordner [`scripts`](./scripts) sind mehrere Workflows als Bashscripts kodiert. (Man kann natürlich ohne sie arbeiten, insbesondere dann, wenn man einen guten IDE hat.)
Zunächst braucht man einen Bashterminal. Das kommt mit OSX (Terminal) und Linux. Für Windows-User braucht man [git-for-windows](https://gitforwindows.org) zu installieren, was auch bash mit installiert. (Und für diejenigen, die VSCode oder andere IDEs benutzen, lässt sich bash als integrierten Terminal im IDE selbst verwenden.)
Den Bashscripts benötigen Ausfuhrrechte. Hierfür führe man
```bash
chmod +x scripts/*.sh;
```
aus. Das muss danach nie wiederholt werden.
Jetzt können wir von dem Hauptordner des Repositorys Befehle wie
```bash
./scripts/build.sh
./scripts/build.sh ---mode setup
```
usw. in der Bash-Console ausführen.
#### Für das Python-Projekt ####
Python version 3.x.x (idealerweise zumindest 3.9.5) plus einige Module (siehe [code/requirements](./code/requirements)). Letztere lassen sich mittels
```bash
# Benutze die Option `--venv true`, um mit virtuellem Env zu arbeiten:
./scripts/build.sh --lang python --mode setup
## oder:
python3 -m pip install -r code/requirements; # linux, osx
py -3 -m pip install -r code/requirements; # Windows
```
installieren.
#### Für das Golang-Projekt ####
Man braucht [go](https://golang.org/dl/) Version **1.17.x**. (Man kann bestimmt bei späteren Releases höhere Versionen benutzen. Man muss lediglich dann in [`./code/golang/go.mod`](./code/golang/go.mod) die Version hochstellen und die Requirements nochmals installieren lassen.) Und einige Packages werden benötigt. Letztere lassen sich mittels
```bash
./scripts/build.sh --lang go --mode setup
```
installieren.
### Ausführung ###
#### Für das Python-Projekt ####
```bash
pushd code/python/src; ## <- auf Pfad mit main.py wechseln
## Anzeigen der Hilfsanleitung:
python3 main.py -h; # linux, OSX
py -3 main.py -h; # Windows
## Algorithmus auf Fälle in code/config.yml ausführen:
python3 main.py run [--debug]; # linux, OSX
py -3 main.py run [--debug]; # Windows
## NOTE: --debug = Infos über Schritte zeigen
## NOTE: --colour true/false = schaltet Farbenmodus ein/aus
popd; ## <- zum vorherigen Pfad zurückwechseln
```
Oder man erstelle ein bash Skript wie `run.sh`, trage die Befehle da ein und führe
```bash
chmod +x run.sh; # nur einmalig nötig
./run.sh
```
aus.
#### Für das Golang-Projekt ####
Zuerst den Artefakt kompilieren:
```bash
./scripts/build.sh --lang go --mode dist;
## oder:
go build -o "dist/ads" "code/golang/main.go";
```
und dann mit dem gebauten Artefakt arbeiten:
```bash
dist/ads # startet Programm im interaktiven Modus
dist/ads help; # zeigt Hilfsanleitung
dist/ads version; # zeigt Version
dist/ads run [--debug]; # Algorithmus auf Fälle in code/config.yml ausführen
dist/ads run [--debug] --it; # startet Programm im interaktiven Modus
## NOTE: --debug = Infos über Schritte zeigen
## NOTE: --colour true/false = schaltet Farbenmodus ein/aus
```
**ANMERKUNG.** Ich habe versucht in beiden Projekten alle unnötigen Komplikationen von den Algorithmen auszublenden. Dennoch kann es durchaus der Fall sein, dass die Python-Implementierung wesentlich einfacher zu verstehen ist als die Go-Implementierung. Das Go-Projekt wurde v.&nbsp;a. deshalb entwickelt, da man mit Python mit _Pointers_ (»Zeiger«, siehe Woche 3) nicht arbeiten kann. Dennoch versuche ich, beide Projekten parallel auf einem ähnlichen Stand zu halten. Beide Projekte sind außerdem so konzipiert, dass sie Inputs gleichen Formats (d. h. die **config.yml** Datei) akzeptieren.
In den Unterordnern
[`code/golang`](./code/golang)
und
[`code/python](./code/python)
kann man Codeprojekte finden.
Dort kann man konkrete Implementierung der Algorithmen ansehen
und ggf. auch auf echte Daten austesten.

66
code/golang/README.md Normal file
View File

@ -0,0 +1,66 @@
# ADS - Golang-Projekt #
**Golang** ist einer relativ moderne Programmiersprache, die immer populärer wird, und viele Vorteile anbietet.
Dieses Projekt ist erneut kein nötiger Bestandteil des Kurses,
sondern nur für Wissbegierige gedacht.
Zunächst bietet sich an, sich die Algorithmen im Unterordner [`internal/algorithms`](./internal/algorithms) anzuschauen,
z.&nbsp;B. [`internal/algorithms/search/binary/binary.go`](./internal/algorithms/search/binary/binary.go) für den Binärsuchalgorithmus,
ohne irgendetwas installieren zu müssen.
**HINWEIS 1:** _Bei meiner Implementierung kann es zu leichten Abweichungen kommen. Bitte **stets** an dem Material im VL-Skript sich orientieren. Der Hauptzweck der Code-Projekte besteht darin, dass Wissbegierige die Algorithmen konkret ausprobieren können. Alle theoretischen Aspekte werden jedoch im Skript und in den Übungen ausführlicher erklärt._
Den Code kann man auch durch die u.&nbsp;s. Anweisungen selber austesten.
**HINWEIS 2:** _Während hier die Anweisungen ausführlich sind und klappen sollten,
bitte nur auf eigener Gewähr diesen Code benutzen._
## Systemvoraussetzungen ##
- **Bash**. Dies kommt mit OSX (Terminal) und Linux. Für Windows-User braucht man [git-for-windows](https://gitforwindows.org) zu installieren, was auch bash mit installiert.
- [**go**](https://golang.org/dl/) Version **1.17.x**. (Man kann bestimmt bei späteren Releases höhere Versionen benutzen. Man muss lediglich dann in [`go.mod`](./go.mod) die Version hochstellen.)
## Setup/Kompilieren ##
1. Requirements (Packages) einmalig mittels
```bash
go get $( cat requirement )
```
installieren. Oder man führe den Befehl
für jede Zeil aus [`requirements`](./requirements) aus,
</br>
z.&nbsp;B. `go get github.com/akamensky/argparse@v1.3.1`
installiert eines der Packages.
2. Codetree mittels
```bash
go build -o ads main.go
```
kompilieren.
</br>
Statt `-o ads` kann man einen beliebigen Pfad verwenden.
</br>
In Unix kann man `-o path/to/folder/ads` verwenden.
</br>
In Windows kann man `-o path/to/folder/ads.exe` verwenden.
## Ausführung ##
Nach Kompilieren wird ein Artefakt namens `ads` gebaut,
den man per Doppelklick ausführen kann.
Alternativ kann man in der Konsole im Ordner mit dem Artefakt einfach
```bash
ads
```
ausführen.
## Entwicklung ##
Gerne kann man den Code benutzen, in einem eigenen Repository weiter entwickeln,
und mit den im Kurs präsentierten Algorithmen und Fällen herumexperimentieren.

View File

@ -1,11 +0,0 @@
Gebrauchsanleitung
~~~~~~~~~~~~~~~~~~
- Version und help:
ads \033[1mversion\033[0m
ads \033[1mhelp\033[0m
- Um die Algorithmen laufen zu lassen
ads \033[1mrun\033[0m [\033[1m--debug\033[0m] [\033[1m--config\033[0m=\033[2m<name of config file>\033[0m]

View File

@ -4,10 +4,10 @@ go 1.17
require (
github.com/akamensky/argparse v1.3.1
github.com/davecgh/go-spew v1.1.0
github.com/davecgh/go-spew v1.1.1
github.com/lithammer/dedent v1.1.0
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/objx v0.1.0
github.com/stretchr/objx v0.3.0
github.com/stretchr/testify v1.7.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

View File

@ -13,7 +13,6 @@ var debugmode bool = false
var ansimode bool = false
var loggingPrefix string = ""
var force bool = false
var tagAll bool = false
var promptSymb string = ">"
func GetQuietMode() bool {

View File

@ -70,9 +70,9 @@ func ParseCli(args []string) (*types.CliArguments, error) {
var err error
Parser = argparse.NewParser("cli parser", "Liest Optionen + Flags von Kommandozeile.")
arguments := types.CliArguments{
ModeHelp: Parser.NewCommand("help", ""),
ModeVersion: Parser.NewCommand("version", "Ruft Endpunkt auf, der die Version anzeigt."),
ModeRun: Parser.NewCommand("run", "Ruft Endpunkt auf, der die Algorithmen laufen lässt."),
ModeHelp: Parser.NewCommand("help", "Hilfsanleitung anzeigen"),
ModeVersion: Parser.NewCommand("version", "Version anzeigen."),
ModeRun: Parser.NewCommand("run", "Algorithmen ausführen."),
Quiet: Parser.Flag("q", "quiet", &optionsQuiet),
Debug: Parser.Flag("", "debug", &optionsDebug),
Interactive: Parser.Flag("", "it", &optionsInteractive),

61
code/python/README.md Normal file
View File

@ -0,0 +1,61 @@
# ADS - Python-Projekt #
**Python** ist eine sehr verbreitete Sprache, die eine Riesencommunity hat.
Sie ist sehr populär unter Wissenschaftlern und Ingenieuren.
Ein Vorteil mit Python ist, dass man sehr leicht und schnell Prototypen entwickeln kann.
Dieses Projekt ist erneut kein nötiger Bestandteil des Kurses,
sondern nur für Wissbegierige gedacht.
Zunächst bietet sich an, sich die Algorithmen im Unterordner [`src/algorithms`](./src/algorithms) anzuschauen,
z.&nbsp;B. [`src/algorithms/search/binary.py`](./src/algorithms/search/binary.py) für den Binärsuchalgorithmus,
ohne irgendetwas installieren zu müssen.
**HINWEIS 1:** _Bei meiner Implementierung kann es zu leichten Abweichungen kommen. Bitte **stets** an dem Material im VL-Skript sich orientieren. Der Hauptzweck der Code-Projekte besteht darin, dass Wissbegierige die Algorithmen konkret ausprobieren können. Alle theoretischen Aspekte werden jedoch im Skript und in den Übungen ausführlicher erklärt._
Den Code kann man auch durch die u.&nbsp;s. Anweisungen selber austesten.
**HINWEIS 2:** _Während hier die Anweisungen ausführlich sind und klappen sollten,
bitte nur auf eigener Gewähr diesen Code benutzen._
### Systemvoraussetzungen ###
- Python version 3.x.x (idealerweise zumindest 3.9.5)
## Setup ##
Requirements (Packages) einmalig mittels
```bash
python3 -m pip install -r requirements; # linux, osx
py -3 -m pip install -r requirements; # Windows
```
installieren lassen.
## Ausführung ##
Zum Anzeigen der Hilfsanleitung in einer Konsole folgenden Befehl ausführen
```bash
python3 src/main.py help; # linux, OSX
py -3 src/main.py help; # Windows
```
Zur Ausführung der Algorithmen auf Fälle in der [Config-Datei](./../config.yml)
in einer Konsole folgenden Befehl ausführen
```bash
python3 src/main.py run; # linux, OSX
py -3 src/main.py run; # Windows
```
Mit dem `--debug` Flag werden Infos über Schritte mit angezeigt.
</br>
Mit dem `--colour true/false` Argument wird der Farbenmodus ein-/ausgeschaltet.
</br>
Mit dem `--config path/to/config` Argument kann man andere Config-Dateien verwenden.
## Entwicklung ##
Gerne kann man den Code benutzen, in einem eigenen Repository weiter entwickeln,
und mit den im Kurs präsentierten Algorithmen und Fällen herumexperimentieren.

3
code/python/assets/LOGO Normal file
View File

@ -0,0 +1,3 @@
+--------------------+
| \033[32;1mAlgoDat I\033[0m |
+--------------------+

View File

@ -0,0 +1 @@
X.Y.Z

View File

@ -0,0 +1,7 @@
info:
title: "App für ADS1"
description: "Interne Configurationsdatei"
options:
display: true
checks: false
metrics: true

View File

@ -5,9 +5,10 @@
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import functools;
import functools
from src.core.log import *;
from src.setup import appconfig;
from src.core.metrics import *;
from src.setup.display import *;
@ -38,8 +39,6 @@ nonnestedAlgorithms = OneShot();
def algorithmInfos(
name: str,
checks: bool = True,
metrics: bool = None,
outputnames: List[str] = ['result'],
preChecks: Any = None,
postChecks: Any = None
@ -67,7 +66,7 @@ def algorithmInfos(
# Initialisierung
DisplayStartOfAlgorithm(name, **inputs);
# Prechecks
if checks and callable(preChecks):
if appconfig.AppConfigPerformChecks() and callable(preChecks):
preChecks(**inputs);
# Metriken initialisieren + starten
ResetMetrics();
@ -85,11 +84,11 @@ def algorithmInfos(
outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]);
outputsNamed = { outputnames[k]: value for k, value in enumerate(outputs_) };
# Letzte Messages
if metrics:
if appconfig.AppConfigShowMetrics():
DisplayMetrics();
DisplayEndOfAlgorithm(**outputsNamed);
# Postchecks
if checks and callable(postChecks):
if appconfig.AppConfigPerformChecks() and callable(postChecks):
postChecks(**inputs, **outputsNamed);
except Exception as e:
nonnestedAlgorithms.state = state1;

View File

@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM binary search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Binärsuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Binärsuchalgorithmus', outputnames=['index'], preChecks=preChecks, postChecks=postChecks)
def BinarySearch(L: List[int], x: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl.

View File

@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM interpolation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames=['index'], 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

@ -36,7 +36,7 @@ def postChecks(L: List[int], i: int, value: int, **_):
# ALGORITHM find ith smallest element
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames=['value'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames=['value'], preChecks=preChecks, postChecks=postChecks)
def FindIthSmallest(L: List[int], i: int) -> int:
'''
Inputs: L = Liste von Zahlen, i = Ordinalzahl
@ -68,7 +68,7 @@ def FindIthSmallest(L: List[int], i: int) -> int:
# ALGORITHM find ith smallest element (D & C)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames=['value'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames=['value'], preChecks=preChecks, postChecks=postChecks)
def FindIthSmallestDC(L: List[int], i: int) -> int:
'''
Inputs: L = Liste von Zahlen, i = Ordinalzahl

View File

@ -39,7 +39,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM jump search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Sprungsuche', outputnames=['index'], 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.
@ -71,7 +71,7 @@ def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
# ALGORITHM jump search - exponentiell
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames=['index'], preChecks=preChecks, postChecks=postChecks)
def JumpSearchExponentiell(L: List[int], x: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl.

View File

@ -36,7 +36,7 @@ def postChecks(L: List[int], index: int, **_):
# ALGORITHM find poison
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames=['index'], preChecks=preChecks, postChecks=postChecks)
def FindPoison(L: List[int]) -> int:
'''
Inputs: L = Liste von Getränken: durch 0-1 Werte wird dargestellt, ob ein Getränk vergiftet ist.
@ -64,7 +64,7 @@ def FindPoison(L: List[int]) -> int:
# ALGORITHM find poison fast
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames=['index'], preChecks=preChecks, postChecks=postChecks)
def FindPoisonFast(L: List[int]) -> int:
'''
Inputs: L = Liste von Getränken: durch 0-1 Werte wird dargestellt, ob ein Getränk vergiftet ist.

View File

@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM sequential search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames=['index'], preChecks=preChecks, postChecks=postChecks)
def SequentialSearch(L: List[int], x: int) -> int:
'''
Inputs: L = Liste von Zahlen, x = Zahl.

View File

@ -33,7 +33,7 @@ def postChecks(L: List[int], **_):
# ALGORITHM max sub sum
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=['maxSum', 'index_from', 'index_to'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=['maxSum', 'index_from', 'index_to'], preChecks=preChecks, postChecks=postChecks)
def MaxSubSum(L: List[float]) -> Tuple[float, int, int]:
'''
Inputs: L = Liste von Zahlen
@ -58,7 +58,7 @@ def MaxSubSum(L: List[float]) -> Tuple[float, int, int]:
# 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)
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme mit D & C)', outputnames=['maxSum', 'index_from', 'index_to'], preChecks=preChecks, postChecks=postChecks)
def MaxSubSumDC(L: List[float]) -> Tuple[float, int, int]:
'''
Inputs: L = Liste von Zahlen

View File

@ -10,6 +10,8 @@ from src.local.misc import *;
from src.local.system import *;
from src.local.typing import *;
from src.core.utils import StripAnsi;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -17,6 +19,7 @@ from src.local.typing import *;
_logging_prefix: str = '';
_quietmode: bool = False;
_debugmode: bool = False;
_ansimode: bool = False;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD get/set quiet mode, logging depth, timer
@ -38,6 +41,14 @@ def SetDebugMode(mode: bool):
_debugmode = mode;
return;
def GetAnsiMode() -> bool:
return _ansimode;
def SetAnsiMode(mode: bool):
global _ansimode;
_ansimode = mode;
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Logging
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -48,7 +59,10 @@ def logGeneric(tag: str, *lines: Any, file: io.TextIOWrapper, force: bool = Fals
tag = '' if tag == '' else tag + ' ';
file = file or sys.stdout;
for line in lines:
print('{}{}{}'.format('', tag, line), file=file);
line = '{}{}{}'.format('', tag, line);
if not _ansimode:
line = StripAnsi(line);
print(line, file=file);
if not tag_all:
tag = '';
return;

View File

@ -0,0 +1,40 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
import re;
from textwrap import dedent;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS ansi
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def StripAnsi(text: str) -> str:
return re.sub(r'\x1b[^m]*m', '', text);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS strings
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def DedentIgnoreFirstLast(text: str) -> str:
text = '\n'.join(re.split(r'\n', text)[1:][:-1])
return dedent(text);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS strings -> bool
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def IsTrue(text: str) -> bool:
text = text.strip();
if re.match(r'^(true|t|yes|y|1|\+|\+1)$', text, re.IGNORECASE):
return True;
return False;
def IsFalse(text: str) -> bool:
text = text.strip();
if re.match(r'^(false|f|no|n|0|-|-1)$', text, re.IGNORECASE):
return True;
return False;

View File

View File

@ -0,0 +1,11 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# EXPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.endpoints.print import version as endpoint_version;
from src.endpoints.print import help as endpoint_help;
from src.endpoints.run import runInteractive as endpoint_runInteractive;
from src.endpoints.run import runNonInteractive as endpoint_runNonInteractive;

View File

@ -0,0 +1,29 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.core.log import *;
from src.setup.cli import GetArgumentsFromCli;
from src.setup.cli import GetArgumentParser;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT version
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def version():
with open('assets/VERSION', 'r') as fp:
version = ('\n'.join(fp.readlines())).strip();
logPlain(version);
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT help
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def help():
parser = GetArgumentParser();
parser.print_help();
return;

View File

@ -0,0 +1,69 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from src.core.log import *;
from src.core.config import *;
from src.setup.display import *;
from src.algorithms.exports import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT run interactive modus
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def runInteractive():
'''
Startet Programm im interaktiven Modus (Konsole).
'''
logWarn('Interaktiver Modus noch nicht implementiert.');
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ENDPOINT run non-interactive
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def runNonInteractive(path: str):
'''
Liest Fälle aus Configdatei aus und führt Algorithmen darauf aus.
'''
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;

View File

@ -8,80 +8,54 @@
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__), '..', '..', '..', '..')));
_path_to_python_project = os.path.abspath(os.path.join(os.path.abspath(__file__), '..', '..'));
sys.path.insert(0, _path_to_python_project);
os.chdir(_path_to_python_project);
from src.core.log import *;
from src.core.config import *;
from src.setup.display import *;
from src.core.utils import IsTrue;
from src.core.utils import IsFalse;
from src.setup.cli import *;
from src.algorithms.exports import *;
from src.setup import appconfig;
from src.endpoints.exports import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES/CONSTANTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
PATH_TO_CONFIG: str = 'code/config.yml';
PATH_TO_CONFIG: str = '../config.yml';
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# MAIN PROCESS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def enter(quiet: bool, debug: bool, mode: str, path: Any, **_):
def enter(
mode: str,
it: bool,
quiet: bool,
debug: bool,
checks: bool,
colour: bool,
config: 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;
SetAnsiMode(colour);
appconfig.SetAppConfigPerformChecks(checks);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# SECONDARY PROCESSES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
config = config if isinstance(config, str) else PATH_TO_CONFIG;
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();
if mode == 'version':
endpoint_version();
return;
elif mode == 'run':
if it:
endpoint_runInteractive();
else:
endpoint_runNonInteractive(path=config);
else: # elif mode
endpoint_help();
return;
return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -91,7 +65,16 @@ def LoopThroughCases(path: str):
if __name__ == '__main__':
sys.tracebacklimit = 0;
try:
args = GetArgumentsFromCli(sys.argv[1:]);
except:
args = GetArgumentsFromCli(*sys.argv[1:]);
except Exception as e:
endpoint_help();
exit(1);
enter(quiet=args.quiet, debug=args.debug, mode=args.mode[0], path=args.path);
enter(
mode=args.mode[0],
it=args.it,
quiet=args.quiet,
debug=args.debug,
checks=IsTrue(args.checks[0]),
colour=IsTrue(args.colour[0]),
config=args.config,
);

View File

@ -0,0 +1,66 @@
#!/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 src.core.config import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_config: Dict[str, bool] = dict(
display = True,
metrics = True,
checks = False,
);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD getters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def AppConfigInitialise():
'''
Extrahiert Inhalte einer YAML Config und parset dies als Struktur
'''
global _config;
config = ReadConfigFile('assets/config.yml');
_config['display'] = GetAttribute(config, 'options', 'display', expectedtype=bool, default=True);
_config['metrics'] = GetAttribute(config, 'options', 'metrics', expectedtype=bool, default=True);
_config['checks'] = GetAttribute(config, 'options', 'checks', expectedtype=bool, default=True);
return;
def AppConfigFancyMode() -> bool:
return _config['display'];
def AppConfigShowMetrics() -> bool:
return _config['metrics'];
def AppConfigPerformChecks() -> bool:
return _config['checks'];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD setters
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def SetAppConfigFancyMode(mode: bool):
global _config;
_config['display'] = mode;
return;
def SetAppConfigShowMetrics(mode: bool):
global _config;
_config['metrics'] = mode;
return;
def SetAppConfigPerformChecks(mode: bool):
global _config;
_config['checks'] = mode;
return;

View File

@ -5,9 +5,11 @@
# IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from argparse import ArgumentError
from src.local.typing import *;
from src.core.log import *;
from src.core.utils import DedentIgnoreFirstLast;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES
@ -24,18 +26,34 @@ def GetArgumentParser() -> argparse.ArgumentParser:
if not isinstance(parser, argparse.ArgumentParser):
parser = argparse.ArgumentParser(
prog='code/main.py',
description=dedent('''
description=DedentIgnoreFirstLast('''
\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.')
parser.add_argument('mode',
nargs=1,
choices=['version', 'help', 'run'],
help=DedentIgnoreFirstLast('''
help = Hilfsanleitung anzeigen.
version = Version anzeigen.
run = Algorithmen ausführen.
'''),
);
parser.add_argument('--it', action='store_true', help='Startet die App im interaktiven Modus.')
parser.add_argument('-q', '--quiet', action='store_true', help='Blendet alle Konsole-Messages aus.')
parser.add_argument('--debug', action='store_true', help='Blendet die Debugging-Befehle ein.')
parser.add_argument('--checks', nargs=1, type=str, default=['False'],
help=DedentIgnoreFirstLast('''
(bool) Ob vor und nach Ausführung von Algorithmen Checks
auf Inputs/Outputs ausgeführt werden sollen.
'''),
),
parser.add_argument('--colour', nargs=1, type=str, default=['False'], help='(bool) Ob Logging färblich angezeigt wird.')
parser.add_argument('--config', nargs=1, type=str, help='(string) Pfad zur Configdatei (nur für run Endpunkt).');
return parser;
def GetArgumentsFromCli(cli_args: List[str]) -> argparse.Namespace:
def GetArgumentsFromCli(*cli_args: str) -> argparse.Namespace:
parser = GetArgumentParser();
return parser.parse_args(cli_args);