Compare commits
136 Commits
4c13c5ff47
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
14f59eeb63 | ||
|
a6cce9626c | ||
|
8d726bf344 | ||
|
04eecdb444 | ||
|
60c47c20c5 | ||
|
89499f524f | ||
|
e55d8708a7 | ||
|
ea7dfc5bef | ||
|
18ece75b67 | ||
|
6541a5246d | ||
|
3505401c7f | ||
|
b193d1d61e | ||
|
ae459547c2 | ||
|
0f1b426f94 | ||
|
cccc6a14ba | ||
|
8d2de4fa2b | ||
|
5c13f8d4cd | ||
fe93d96584 | |||
580cc97387 | |||
ef833533f6 | |||
ab38c181c9 | |||
972027ce41 | |||
2d91e98904 | |||
9a56c63018 | |||
d878c0b77d | |||
a7f3377677 | |||
eaef3322d8 | |||
9e04763782 | |||
924104408f | |||
3a4702429b | |||
9237dbfad0 | |||
dbdb6a8480 | |||
337790f3cd | |||
38025247c7 | |||
1fd932c0ef | |||
66e0f912e3 | |||
7b655a1c0a | |||
85ba0a0936 | |||
8f08634720 | |||
6f1ee1b85f | |||
c14efb0cc6 | |||
30dffa20d4 | |||
6bf15f936e | |||
f0d0c9ef8a | |||
1934c3475a | |||
a96d1bb6c9 | |||
31b3c19bf9 | |||
552c3197e8 | |||
701032a109 | |||
01dd4e1537 | |||
be6fc48c0b | |||
1a387ac308 | |||
d6bc4b9d72 | |||
6b5c81c276 | |||
be9ce8bb82 | |||
47414d6d60 | |||
f7ef295ec8 | |||
f55677ed8b | |||
324b8d2fcd | |||
53978d584b | |||
893db52d90 | |||
43f5447ed7 | |||
e9f83317d8 | |||
6d97bcc6db | |||
e8e36113be | |||
d157cd3e92 | |||
fce25de013 | |||
8cd99c1632 | |||
10bad8fcd9 | |||
d0fa57b46d | |||
7e2399c819 | |||
7f5f3e9541 | |||
f563c8e6e9 | |||
a38f18ee81 | |||
2c23f4c728 | |||
15c2c37213 | |||
189755e69a | |||
e6be5a467c | |||
f4287dfd8f | |||
37dea15b2b | |||
f01710b445 | |||
5b17c2ce35 | |||
619c6c209c | |||
dccb8e8af2 | |||
196704d7bb | |||
699a5f6fa4 | |||
aab7844218 | |||
e9dad73a05 | |||
dac99c0fa0 | |||
38db023f99 | |||
e583266394 | |||
902b7b593c | |||
01f69adcfb | |||
ecbf274be6 | |||
82962e376d | |||
965cd48ae6 | |||
8ddb4fa427 | |||
3f3ccf1059 | |||
60b27c1abe | |||
ab2473af9e | |||
81160e7e54 | |||
76f9354fa4 | |||
9b1751fa5d | |||
62e1e7dcca | |||
64df98fcf3 | |||
2c94de5854 | |||
431092d069 | |||
0faca1e6bb | |||
3941348420 | |||
f4b2ca6c90 | |||
964fd80888 | |||
a95e3ed8c1 | |||
a706faa8b8 | |||
e03f07d555 | |||
ab0fd15093 | |||
96968cf8dd | |||
aa7c983e99 | |||
85bd7d4f41 | |||
2693b6768c | |||
c8868d5bf4 | |||
d18957351d | |||
e0f36f2625 | |||
e3d8de8888 | |||
799b91c2d5 | |||
a83c5a91fc | |||
c0e1bdc3c4 | |||
210a3c45eb | |||
14fad54a57 | |||
5875fb4a90 | |||
71d87423fe | |||
379d660c89 | |||
e65b5dc51b | |||
8a858ad17c | |||
c5b93eb3e3 | |||
d77da0a327 | |||
42368fd216 |
12
.env
Normal file
12
.env
Normal file
@ -0,0 +1,12 @@
|
||||
# General
|
||||
NAME_OF_APP="ads"
|
||||
REQUIREMENTS_PY="code/python/requirements"
|
||||
REQUIREMENTS_GO="code/golang/requirements"
|
||||
TEST_TIMEOUT="10s"
|
||||
|
||||
# Logging
|
||||
CONSOLE_OUT=/dev/stdout
|
||||
CONSOLE_ERR=/dev/stderr
|
||||
CONSOLE_VERBOSE=/dev/null
|
||||
CONSOLE_PATH_LOGS=logs
|
||||
CONSOLE_FILENAME_LOGS_DEBUG=debug.log
|
10
.gitignore
vendored
10
.gitignore
vendored
@ -5,6 +5,7 @@
|
||||
# MAIN FOLDER
|
||||
################################################################
|
||||
|
||||
!/.env
|
||||
!/README.md
|
||||
|
||||
################################################################
|
||||
@ -19,7 +20,16 @@
|
||||
!/protocol/README.md
|
||||
!/protocol/woche*.md
|
||||
|
||||
!/scripts
|
||||
!/scripts/*.sh
|
||||
|
||||
!/code
|
||||
!/code/python
|
||||
!/code/golang
|
||||
!/code/config.yml
|
||||
|
||||
!/dist
|
||||
!/dist/VERSION
|
||||
|
||||
################################################################
|
||||
# ARTEFACTS
|
||||
|
30
README.md
30
README.md
@ -1,12 +1,36 @@
|
||||
# Algorithmen und Datenstrukturen I, WiSe 2021-22 #
|
||||
|
||||
Diese Repository ist für die Übungsgruppe am Freitag um 13:15–14:45.
|
||||
Diese Repository ist für die Seminargruppe **j/l** am Freitag um 13:15–14:45
|
||||
im Raum SG 3-14 bzw. SG 4-10 (alternierend).
|
||||
|
||||
**HINWEIS:** In diesem Repository werden keine persönlichen Daten gespeichert.
|
||||
**HINWEIS 1:** In diesem Repository werden keine Personen bezogenen Daten der Studierenden gespeichert.
|
||||
|
||||
**HINWEIS 2:** Es besteht absolut gar keine Pflicht, die Materialien in diesem Repo zu verwenden. Diese sind lediglich zusätzliche Hilfsmittel. **Im Zweifelsfalls** sollte man sich immer an den Definitionen und Auslegungen in der VL orientieren.
|
||||
|
||||
In diesem Repository findet man:
|
||||
|
||||
- Protokolle der Übungsgruppe [hier](./protocol).
|
||||
- Protokolle der Seminargruppe [hier](./protocol).
|
||||
- Notizen [hier](./notes).
|
||||
- Symbolverzeichnis unter [notes/glossar.md](./notes/glossar.md).
|
||||
- Referenzen unter [notes/quellen.md](./notes/quellen.md).
|
||||
|
||||
## Leistungen während des Semesters ##
|
||||
|
||||
- 12 x freiwillige Serien (unkorrigiert: Lösungen werden per Moodle veröffentlicht)
|
||||
- 6 x Pflichtserien (jeweils 2 Wochen Bearbeitungsdauer)
|
||||
- wöchentlich werden im den Lernstunden _andere_ Aufgabenblätter im Raum angezeigt und von Studierenden bearbeitet.
|
||||
|
||||
## Vorleistungen ##
|
||||
|
||||
- ≥ 50% der Punkte aus den 6 Pflichtserien sollen geschafft werden.
|
||||
- _nur digitale Abgabe_!
|
||||
|
||||
## Code ##
|
||||
|
||||
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.
|
||||
|
95
code/config.yml
Normal file
95
code/config.yml
Normal file
@ -0,0 +1,95 @@
|
||||
info:
|
||||
title: AlgoDat I, WiSe 2021/22
|
||||
description: Testfälle für Algorithmen.
|
||||
parts:
|
||||
## Hier kann man beliebig viele Testfälle einfügen mit beliebigen Eingaben (solange gültig!)
|
||||
cases:
|
||||
- command: 'algorithm-sum-maxsub'
|
||||
inputs:
|
||||
L: [5, -6, 4, 2, -5, 7, -2, -7, 3, 5]
|
||||
- command: 'algorithm-sum-maxsub-dc'
|
||||
inputs:
|
||||
L: [5, -6, 4, 2, -5, 7, -2, -7, 3, 5]
|
||||
- command: 'algorithm-search-sequential'
|
||||
inputs:
|
||||
L: [1, 3, 5, 7, 11, 13, 17, 19, 23]
|
||||
x: 13
|
||||
- command: 'algorithm-search-binary'
|
||||
inputs:
|
||||
L: [1, 3, 5, 7, 11, 13, 17, 19, 23]
|
||||
x: 13
|
||||
- command: 'algorithm-search-interpolation'
|
||||
inputs:
|
||||
L: [1, 3, 5, 7, 11, 13, 17, 19, 23]
|
||||
x: 13
|
||||
- command: 'algorithm-search-jump'
|
||||
inputs:
|
||||
L: [1, 3, 5, 7, 11, 13, 16, 17, 23, 33, 34, 35]
|
||||
x: 17
|
||||
m: 3
|
||||
- command: 'algorithm-search-jump-exp'
|
||||
inputs:
|
||||
L: [1, 3, 5, 7, 11, 13, 16, 17, 23, 33, 34, 35]
|
||||
x: 17
|
||||
m: 3
|
||||
## Freiwilliges ÜB 2, Aufgabe 4, Beispiel
|
||||
- command: 'algorithm-search-poison'
|
||||
description: 'Freiwilliges ÜB2, A4, Beispiel'
|
||||
inputs: &ref_inputs_ueb2_4
|
||||
L: [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]
|
||||
- command: 'algorithm-search-poison-fast'
|
||||
description: 'Freiwilliges ÜB2, A4, Beispiel'
|
||||
inputs: *ref_inputs_ueb2_4
|
||||
## Freiwilliges ÜB 2, Aufgabe 5
|
||||
- command: 'algorithm-search-binary'
|
||||
description: 'Freiwilliges ÜB2, A5a'
|
||||
inputs: &ref_inputs_ueb2_5
|
||||
L: [4, 11, 22, 23, 25, 27, 29, 36, 41, 52, 64, 76, 82, 86, 94, 96, 102, 117, 123, 147, 188, 211, 216, 222, 224, 226, 233, 239, 255, 263, 277, 289]
|
||||
x: 114
|
||||
- command: 'algorithm-search-jump'
|
||||
description: 'Freiwilliges ÜB2, A5b'
|
||||
inputs:
|
||||
<<: *ref_inputs_ueb2_5
|
||||
m: 5
|
||||
- command: 'algorithm-search-interpolation'
|
||||
description: 'Freiwilliges ÜB2, A5c'
|
||||
inputs: *ref_inputs_ueb2_5
|
||||
## Freiwilliges ÜB 2, Aufgabe 6
|
||||
- command: 'algorithm-search-ith-element'
|
||||
description: 'Freiwilliges ÜB2, A6a'
|
||||
inputs: &ref_inputs_ueb2_6a
|
||||
L: [16, 15, 9, 5, 1, 10, 7, 14, 19, 8]
|
||||
i: 2
|
||||
- command: 'algorithm-search-ith-element-dc'
|
||||
description: 'Freiwilliges ÜB2, A6a (D&C)'
|
||||
inputs: *ref_inputs_ueb2_6a
|
||||
- command: 'algorithm-search-ith-element'
|
||||
description: 'Freiwilliges ÜB2, A6b'
|
||||
inputs: &ref_inputs_ueb2_6b
|
||||
<<: *ref_inputs_ueb2_6a
|
||||
i: 5
|
||||
- command: 'algorithm-search-ith-element-dc'
|
||||
description: 'Freiwilliges ÜB2, A6b (D&C)'
|
||||
inputs: *ref_inputs_ueb2_6b
|
||||
# SEMINARBLATT 3
|
||||
- command: 'algorithm-search-binary'
|
||||
description: 'Seminarblatt Woche 3, Aufgabe 1'
|
||||
inputs: &ref_inputs_sem3_1
|
||||
L: [7, 12, 29, 33, 40, 44, 45, 55, 64, 68, 78, 81, 84, 89, 95, 117, 120, 124, 133, 148, 152, 157, 174, 209, 219, 226, 226, 237, 241, 273, 277, 282]
|
||||
x: 101
|
||||
- command: 'algorithm-search-jump'
|
||||
description: 'Seminarblatt Woche 3, Aufgabe 1'
|
||||
inputs:
|
||||
<<: *ref_inputs_sem3_1
|
||||
m: 5
|
||||
- command: 'algorithm-search-interpolation'
|
||||
description: 'Seminarblatt Woche 3, Aufgabe 1'
|
||||
inputs: *ref_inputs_sem3_1
|
||||
- command: 'algorithm-stacks-next-greater-element'
|
||||
description: 'Seminarblatt Woche 4, Aufgabe 1'
|
||||
inputs:
|
||||
L: [4, 6, 3, 16]
|
||||
- command: 'algorithm-stacks-next-greater-element'
|
||||
description: 'Seminarblatt Woche 4, Aufgabe 1 mit anderen Daten'
|
||||
inputs:
|
||||
L: [20, 10, 10, 2, 1, 5, 30, 3, 16]
|
33
code/golang/.gitignore
vendored
Normal file
33
code/golang/.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
*
|
||||
!/.gitignore
|
||||
|
||||
################################################################
|
||||
# MAIN FOLDER
|
||||
################################################################
|
||||
|
||||
!/Makefile
|
||||
!/README.md
|
||||
!/requirements
|
||||
|
||||
################################################################
|
||||
# PROJECT FILES
|
||||
################################################################
|
||||
|
||||
!/assets
|
||||
!/assets/VERSION
|
||||
!/assets/LOGO
|
||||
!/assets/config.yml
|
||||
|
||||
!/pkg
|
||||
!/internal
|
||||
!/*/**/
|
||||
!/*/**/*.go
|
||||
!/go.mod
|
||||
!/go.sum
|
||||
|
||||
################################################################
|
||||
# ARTEFACTS
|
||||
################################################################
|
||||
|
||||
/**/.DS_Store
|
||||
/**/__archive__*
|
27
code/golang/Makefile
Normal file
27
code/golang/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# LOCAL ARGUMENTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
PATH_TO_CONFIG:=../config.yml#<- kann durch Pfad zur eigenen yml-Datei ersetzt werden
|
||||
PATH_TO_ARTEFACT:=../../dist/ads#<- kann beliebiger Pfad sein
|
||||
COLOUR:=true
|
||||
|
||||
## für Windows weichen Defaultsettings leicht ab:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
PATH_TO_ARTEFACT:=${PATH_TO_ARTEFACT}.exe
|
||||
COLOUR:=false# <- man kann als 'true' setzen, aber in Windows funktioniert es möglicherweise nicht
|
||||
endif
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# TARGETS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
setup:
|
||||
go mod download
|
||||
build:
|
||||
go build -o ${PATH_TO_ARTEFACT} main.go
|
||||
run: # non-interactive mode mit config-datei
|
||||
${PATH_TO_ARTEFACT} run --debug --colour ${COLOUR} --config "${PATH_TO_CONFIG}"
|
||||
run-it: # interactive mode
|
||||
${PATH_TO_ARTEFACT} run --it --debug --colour ${COLOUR}
|
||||
# Do everything:
|
||||
all: setup build run
|
||||
all-it: setup build run-it
|
88
code/golang/README.md
Normal file
88
code/golang/README.md
Normal file
@ -0,0 +1,88 @@
|
||||
# ADS - Golang-Projekt #
|
||||
|
||||
**Golang** ist eine 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 [`pkg/algorithms`](./pkg/algorithms) anzuschauen,
|
||||
z. B. [`pkg/algorithms/search/binary/binary.go`](./pkg/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. 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.)
|
||||
|
||||
Alle u. s. Befehle sollen in einer Bash-Konsole von diesem Ordner aus ausgeführt werden.
|
||||
|
||||
## Einrichten mittels **Makefile** ##
|
||||
|
||||
Führe jeweils
|
||||
|
||||
```bash
|
||||
make setup
|
||||
make build
|
||||
make run
|
||||
# oder für interaktiven Modus
|
||||
make run-it
|
||||
```
|
||||
|
||||
aus, um Packages zu installieren
|
||||
bzw. den Code zu kompilieren
|
||||
bzw. den Code auszuführen.
|
||||
Siehe [`Makefile`](./Makefile) für Details zu den Vorgängen.
|
||||
|
||||
Wer Makefile benutzt kann die u. s. Anweisungen ignorieren.
|
||||
|
||||
## Setup/Kompilieren ##
|
||||
|
||||
|
||||
1. Requirements (Packages) einmalig mittels
|
||||
|
||||
```bash
|
||||
go get $( cat requirements )
|
||||
```
|
||||
|
||||
installieren. Oder man führe den Befehl
|
||||
für jede Zeile aus [`requirements`](./requirements) aus,
|
||||
</br>
|
||||
z. 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.
|
3
code/golang/assets/LOGO
Normal file
3
code/golang/assets/LOGO
Normal file
@ -0,0 +1,3 @@
|
||||
+--------------------+
|
||||
| \033[32;1mAlgoDat I\033[0m |
|
||||
+--------------------+
|
1
code/golang/assets/VERSION
Normal file
1
code/golang/assets/VERSION
Normal file
@ -0,0 +1 @@
|
||||
0.0.0
|
7
code/golang/assets/config.yml
Normal file
7
code/golang/assets/config.yml
Normal file
@ -0,0 +1,7 @@
|
||||
info:
|
||||
title: "App für ADS1"
|
||||
description: "Interne Configurationsdatei"
|
||||
options:
|
||||
display: true
|
||||
checks: false
|
||||
metrics: true
|
13
code/golang/go.mod
Normal file
13
code/golang/go.mod
Normal file
@ -0,0 +1,13 @@
|
||||
module ads
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
github.com/akamensky/argparse v1.3.1
|
||||
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.3.0
|
||||
github.com/stretchr/testify v1.7.0
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
)
|
21
code/golang/go.sum
Normal file
21
code/golang/go.sum
Normal file
@ -0,0 +1,21 @@
|
||||
github.com/akamensky/argparse v1.3.1 h1:kP6+OyvR0fuBH6UhbE6yh/nskrDEIQgEA1SUXDPjx4g=
|
||||
github.com/akamensky/argparse v1.3.1/go.mod h1:S5kwC7IuDcEr5VeXtGPRVZ5o/FdhcMlQz4IZQuw64xA=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
|
||||
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.3.0 h1:NGXK3lHquSN08v5vWalVI/L8XU9hdzE/G6xsrze47As=
|
||||
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
42
code/golang/internal/core/logging/logging.go
Normal file
42
code/golang/internal/core/logging/logging.go
Normal file
@ -0,0 +1,42 @@
|
||||
package logging
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* MAIN METHODS logging
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func Plain(line interface{}, args ...interface{}) {
|
||||
logGeneric(os.Stdout, "", line, args...)
|
||||
}
|
||||
|
||||
func Info(line interface{}, args ...interface{}) {
|
||||
logGeneric(os.Stdout, "[\033[94;1mINFO\033[0m]", line, args...)
|
||||
}
|
||||
|
||||
func Debug(line interface{}, args ...interface{}) {
|
||||
if !debugmode {
|
||||
return
|
||||
}
|
||||
logGeneric(os.Stdout, "\033[2m[\033[96;1mDEBUG\033[0m\033[2m]\033[0m", fmt.Sprintf("\033[2m%v\033[0m", line), args...)
|
||||
}
|
||||
|
||||
func Warn(line interface{}, args ...interface{}) {
|
||||
logGeneric(os.Stdout, "[\033[93;1mWARNING\033[0m]", line, args...)
|
||||
}
|
||||
|
||||
func Error(line interface{}, args ...interface{}) {
|
||||
logGeneric(os.Stderr, "[\033[91;1mERROR\033[0m]", line, args...)
|
||||
}
|
||||
|
||||
func Fatal(line interface{}, args ...interface{}) {
|
||||
logGeneric(os.Stderr, "[\033[91;1mFATAL\033[0m]", line, args...)
|
||||
os.Exit(1)
|
||||
}
|
45
code/golang/internal/core/logging/logging_auxiliary.go
Normal file
45
code/golang/internal/core/logging/logging_auxiliary.go
Normal file
@ -0,0 +1,45 @@
|
||||
package logging
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* AUXILIARY METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func logGeneric(pipe *os.File, tag string, line interface{}, args ...interface{}) {
|
||||
if !force && quietmode {
|
||||
return
|
||||
}
|
||||
if !(tag == "") {
|
||||
tag = tag + " "
|
||||
}
|
||||
fmt.Fprintln(pipe, decorateLine(loggingPrefix, tag, expandLine(line, args)))
|
||||
}
|
||||
|
||||
func expandLine(line interface{}, args []interface{}) string {
|
||||
return fmt.Sprintf(fmt.Sprintf("%s", line), args...)
|
||||
}
|
||||
|
||||
func decorateLine(loggingPrefix string, tag string, line string) string {
|
||||
return stripAnsiIfNecessary(fmt.Sprintf("%[1]s%[2]s%[3]v", loggingPrefix, tag, line))
|
||||
}
|
||||
|
||||
func stripAnsiIfNecessary(line string) string {
|
||||
if !ansimode {
|
||||
line = utils.StripAnsi(line)
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
func ClearScreen() {
|
||||
fmt.Print("\033[2J")
|
||||
}
|
46
code/golang/internal/core/logging/logging_prompt.go
Normal file
46
code/golang/internal/core/logging/logging_prompt.go
Normal file
@ -0,0 +1,46 @@
|
||||
package logging
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"ads/pkg/re"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD prompts
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Zeigt Prompt an und liest Usereingabe aus, erkennt auch ob Meta+D geklickt wurde
|
||||
func Prompt(lines ...interface{}) (string, bool, error) {
|
||||
pipe := os.Stdout
|
||||
if len(lines) > 0 {
|
||||
tag := ""
|
||||
for _, line := range lines {
|
||||
logGeneric(pipe, tag, line)
|
||||
}
|
||||
logGeneric(pipe, tag, "")
|
||||
}
|
||||
fmt.Fprintf(pipe, "%s ", promptSymb)
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
line, err := reader.ReadString('\n')
|
||||
line = re.Sub(`\s+$`, "", line)
|
||||
if err != nil && err == io.EOF {
|
||||
fmt.Fprintln(pipe, "")
|
||||
return line, true, err
|
||||
}
|
||||
return line, false, err
|
||||
}
|
||||
|
||||
func PromptAnyKeyToContinue() bool {
|
||||
pipe := os.Stdout
|
||||
fmt.Fprint(pipe, stripAnsiIfNecessary("\033[2;3mEingabetaste (Enter) zum Fortsetzen drücken:\033[0m "))
|
||||
_, exit, _ := Prompt()
|
||||
return exit
|
||||
}
|
48
code/golang/internal/core/logging/logging_settings.go
Normal file
48
code/golang/internal/core/logging/logging_settings.go
Normal file
@ -0,0 +1,48 @@
|
||||
package logging
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var quietmode bool = false
|
||||
var debugmode bool = true
|
||||
var ansimode bool = false
|
||||
var loggingPrefix string = ""
|
||||
var force bool = false
|
||||
var promptSymb string = ">"
|
||||
|
||||
func GetQuietMode() bool {
|
||||
return quietmode
|
||||
}
|
||||
|
||||
func SetQuietMode(mode bool) {
|
||||
quietmode = mode
|
||||
}
|
||||
|
||||
func GetDebugMode() bool {
|
||||
return debugmode
|
||||
}
|
||||
|
||||
func SetDebugMode(mode bool) {
|
||||
debugmode = mode
|
||||
}
|
||||
|
||||
func GetAnsiMode() bool {
|
||||
return ansimode
|
||||
}
|
||||
|
||||
func SetAnsiMode(mode bool) {
|
||||
ansimode = mode
|
||||
}
|
||||
|
||||
func GetForce() bool {
|
||||
return force
|
||||
}
|
||||
|
||||
func SetForce(mode bool) {
|
||||
force = mode
|
||||
}
|
90
code/golang/internal/core/metrics/metrics.go
Normal file
90
code/golang/internal/core/metrics/metrics.go
Normal file
@ -0,0 +1,90 @@
|
||||
package metrics
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/types"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var _ctr_time = types.NewCounter()
|
||||
var _ctr_moves = types.NewCounter()
|
||||
var _ctr_space = types.NewCounter()
|
||||
var _tmr = types.NewTimer()
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func ResetMetrics() {
|
||||
_ctr_time.Reset()
|
||||
_ctr_moves.Reset()
|
||||
_ctr_space.Reset()
|
||||
_tmr.Reset()
|
||||
}
|
||||
|
||||
func StartMetrics() {
|
||||
_tmr.Start()
|
||||
}
|
||||
|
||||
func StopMetrics() {
|
||||
_tmr.Stop()
|
||||
}
|
||||
|
||||
func AddTimeCost(options ...int) {
|
||||
_ctr_time.Add(options...)
|
||||
}
|
||||
|
||||
func AddMovesCost(options ...int) {
|
||||
_ctr_moves.Add(options...)
|
||||
}
|
||||
|
||||
func AddSpaceCost(options ...int) {
|
||||
_ctr_space.Add(options...)
|
||||
}
|
||||
|
||||
func SetSpaceCost(n int) {
|
||||
_ctr_space.Set(n)
|
||||
}
|
||||
|
||||
func GetTimeCost() int {
|
||||
return _ctr_time.Size()
|
||||
}
|
||||
|
||||
func GetMovesCost() int {
|
||||
return _ctr_moves.Size()
|
||||
}
|
||||
|
||||
func GetSpaceCost() int {
|
||||
return _ctr_space.Size()
|
||||
}
|
||||
|
||||
func GetTimeElapsed() time.Duration {
|
||||
return _tmr.ElapsedTime()
|
||||
}
|
||||
|
||||
func GetTimeElapsedLongFormat() string {
|
||||
t := _tmr.ElapsedTime()
|
||||
h := utils.Floor(t.Hours())
|
||||
m := utils.Floor(t.Minutes()) - h*60
|
||||
s := t.Seconds() - float64(m*60)
|
||||
h_string := fmt.Sprintf("%v", h)
|
||||
for len(h_string) < 2 {
|
||||
h_string = "0" + h_string
|
||||
}
|
||||
m_string := fmt.Sprintf("%v", m)
|
||||
for len(m_string) < 2 {
|
||||
m_string = "0" + m_string
|
||||
}
|
||||
s_string := fmt.Sprintf("%f", s)
|
||||
return fmt.Sprintf("%[1]s:%[2]s:%[3]s", h_string, m_string, s_string)
|
||||
}
|
104
code/golang/internal/core/utils/utils_arrays.go
Normal file
104
code/golang/internal/core/utils/utils_arrays.go
Normal file
@ -0,0 +1,104 @@
|
||||
package utils
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD array contains
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func ArrayContains(x interface{}, elem interface{}) bool {
|
||||
xAsArray := reflect.ValueOf(x)
|
||||
if xAsArray.Kind() == reflect.Slice {
|
||||
for i := 0; i < xAsArray.Len(); i++ {
|
||||
if xAsArray.Index(i).Interface() == elem {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD sort
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func IsSortedListInt(X []int) bool {
|
||||
n := len(X)
|
||||
for i, x := range X {
|
||||
for j := i + 1; j < n; j++ {
|
||||
if X[j] < x {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD insert, pop
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func PopIndexListInt(X []int, index int) []int {
|
||||
// NOTE: aus irgendeinem Grund reicht es nicht aus mit X zu arbeiten, denn sonst die u. s. Zeile überschreibt X
|
||||
X_ := make([]int, len(X))
|
||||
copy(X_, X)
|
||||
return append(X_[:index], X_[(index+1):]...)
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD unique
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func UniqueListInt(X []int) []int {
|
||||
var ok bool
|
||||
m := map[int]bool{}
|
||||
X_unique := []int{}
|
||||
for _, x := range X {
|
||||
if _, ok = m[x]; !ok {
|
||||
X_unique = append(X_unique, x)
|
||||
}
|
||||
}
|
||||
return X_unique
|
||||
}
|
||||
|
||||
func ContainsNoDuplicatesListInt(X []int) bool {
|
||||
return len(X) <= len(UniqueListInt(X))
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD get value from array of unknown length
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func GetArrayStringValue(arr *[]string, index int, Default string) string {
|
||||
if arr != nil && len(*arr) > index {
|
||||
return (*arr)[index]
|
||||
}
|
||||
return Default
|
||||
}
|
||||
|
||||
func GetArrayBoolValue(arr *[]bool, index int, Default bool) bool {
|
||||
if arr != nil && len(*arr) > index {
|
||||
return (*arr)[index]
|
||||
}
|
||||
return Default
|
||||
}
|
||||
|
||||
func GetArrayIntValue(arr *[]int, index int, Default int) int {
|
||||
if arr != nil && len(*arr) > index {
|
||||
return (*arr)[index]
|
||||
}
|
||||
return Default
|
||||
}
|
||||
|
||||
func GetArrayInterfaceValue(arr *[](interface{}), index int, Default interface{}) interface{} {
|
||||
if arr != nil && len(*arr) > index {
|
||||
return (*arr)[index]
|
||||
}
|
||||
return Default
|
||||
}
|
147
code/golang/internal/core/utils/utils_maths.go
Normal file
147
code/golang/internal/core/utils/utils_maths.go
Normal file
@ -0,0 +1,147 @@
|
||||
package utils
|
||||
|
||||
/*
|
||||
In Golang sind manche (basic!) mathematischen Vorgänge etwas umständlich zu implementieren.
|
||||
Wir wollen diese Methoden komplett einhüllen, damit wir von ihrer Komplexität
|
||||
in den Algorithmen nicht abgelenkt werden.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD floor, ceil
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func Floor(x float64) int {
|
||||
return int(math.Floor(x))
|
||||
}
|
||||
|
||||
func Ceil(x float64) int {
|
||||
return int(math.Ceil(x))
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD max, min
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func MinInt(x int, y ...int) int {
|
||||
if len(y) == 0 {
|
||||
return x
|
||||
} else if x < y[0] {
|
||||
return MinInt(x, y[1:]...)
|
||||
} else {
|
||||
return MinInt(y[0], y[1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
func MaxInt(x int, y ...int) int {
|
||||
if len(y) == 0 {
|
||||
return x
|
||||
} else if x > y[0] {
|
||||
return MaxInt(x, y[1:]...)
|
||||
} else {
|
||||
return MaxInt(y[0], y[1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
func ArgMinInt(X []int) int {
|
||||
if len(X) == 0 {
|
||||
return -1
|
||||
}
|
||||
minValue := X[0]
|
||||
index := 0
|
||||
for i, x := range X {
|
||||
if x < minValue {
|
||||
minValue = x
|
||||
index = i
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
func ArgMaxInt(X []int) int {
|
||||
if len(X) == 0 {
|
||||
return -1
|
||||
}
|
||||
maxValue := X[0]
|
||||
index := 0
|
||||
for i, x := range X {
|
||||
if x > maxValue {
|
||||
maxValue = x
|
||||
index = i
|
||||
}
|
||||
}
|
||||
return index
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD sum
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func SumListInt(X []int) int {
|
||||
result := 0
|
||||
for _, x := range X {
|
||||
result += x
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func SumListFloat(X []float64) float64 {
|
||||
result := 0.
|
||||
for _, x := range X {
|
||||
result += x
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS binary
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Für eine Zahl n != 0 liefert die Länge der binären Darstellung der Zahl,
|
||||
und für n == 0 liefert 0
|
||||
*/
|
||||
func LengthOfBinary(number int) int {
|
||||
if number == 0 {
|
||||
return 0
|
||||
}
|
||||
if number < 0 {
|
||||
number = -number
|
||||
}
|
||||
number_binary := fmt.Sprintf("%b", int64(number))
|
||||
return len([]rune(number_binary))
|
||||
}
|
||||
|
||||
/*
|
||||
Für eine Zahl n != 0 liefert die Bits der binären Darstellung
|
||||
*/
|
||||
func IntToBinary(number int) []int {
|
||||
if number == 0 || number == 1 {
|
||||
return []int{number}
|
||||
}
|
||||
number_binary := fmt.Sprintf("%b", int64(number))
|
||||
runes := []rune(number_binary)
|
||||
bits := make([]int, len(runes))
|
||||
for i, rune := range runes {
|
||||
bit, _ := strconv.ParseInt(fmt.Sprintf("%c", rune), 2, 64)
|
||||
bits[len(runes)-1-i] = int(bit)
|
||||
}
|
||||
return bits
|
||||
}
|
||||
|
||||
func NthBit(number int, digit int) int {
|
||||
bits := IntToBinary(number)
|
||||
if digit < len(bits) {
|
||||
return bits[digit]
|
||||
}
|
||||
return 0
|
||||
}
|
76
code/golang/internal/core/utils/utils_strings.go
Normal file
76
code/golang/internal/core/utils/utils_strings.go
Normal file
@ -0,0 +1,76 @@
|
||||
package utils
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/lithammer/dedent"
|
||||
|
||||
"ads/pkg/re"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD dedent textblock and expand escaped symbols
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func DedentIgnoreEmptyLines(text string) string {
|
||||
return dedent.Dedent(text)
|
||||
}
|
||||
|
||||
func DedentIgnoreFirstAndLast(text string) string {
|
||||
text = re.Sub(`^\s*[\n\r]|[\n\r]\s*$`, ``, text)
|
||||
return DedentIgnoreEmptyLines(text)
|
||||
}
|
||||
|
||||
func DedentAndExpand(text string) string {
|
||||
var err error
|
||||
var result []string
|
||||
result = []string{}
|
||||
text = dedent.Dedent(text)
|
||||
lines := strings.Split(text, "\n")
|
||||
for _, line := range lines {
|
||||
line = fmt.Sprintf(`"%s"`, line)
|
||||
line, err = strconv.Unquote(line)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
result = append(result, line)
|
||||
}
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
func FormatTextBlockAsList(text string, options ...bool) []string {
|
||||
var unindent bool = GetArrayBoolValue(&options, 0, true)
|
||||
if unindent {
|
||||
text = DedentIgnoreFirstAndLast(text)
|
||||
}
|
||||
return re.Split(`\n`, text)
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS ansi
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func StripAnsi(text string) string {
|
||||
return re.Sub(`\x1b[^m]*m`, ``, text)
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS string -> bool
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func IsTrue(text string) bool {
|
||||
text = strings.TrimSpace(text)
|
||||
return re.Matches(`(?i)(^(true|t|yes|y|1|\+|\+1)$)`, text)
|
||||
}
|
||||
|
||||
func IsFalse(text string) bool {
|
||||
text = strings.TrimSpace(text)
|
||||
return re.Matches(`(?i)(^(false|f|no|n|0|-|-1)$)`, text)
|
||||
}
|
34
code/golang/internal/endpoints/print/print.go
Normal file
34
code/golang/internal/endpoints/print/print.go
Normal file
@ -0,0 +1,34 @@
|
||||
package print
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/setup"
|
||||
"ads/internal/setup/cli"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ENDPOINT version
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func Version() {
|
||||
logging.SetForce(true)
|
||||
logging.Plain(setup.Version())
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ENDPOINT help
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func Help() {
|
||||
logging.SetForce(true)
|
||||
cli.ParseCli([]string{}) // <- generiere leere Instanz für Parser, um voll Hilfsanleitug zu zeigen
|
||||
logging.Plain("")
|
||||
logging.Plain(setup.Logo())
|
||||
// logging.Plain(setup.Help())
|
||||
logging.Plain(cli.Parser.Usage(nil))
|
||||
logging.Plain("")
|
||||
}
|
173
code/golang/internal/endpoints/run/run.go
Normal file
173
code/golang/internal/endpoints/run/run.go
Normal file
@ -0,0 +1,173 @@
|
||||
package run
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/setup"
|
||||
"ads/internal/types"
|
||||
|
||||
algorithm_search_binary "ads/pkg/algorithms/search/binary"
|
||||
algorithm_search_interpol "ads/pkg/algorithms/search/interpol"
|
||||
algorithm_search_ith_element "ads/pkg/algorithms/search/ith_element"
|
||||
algorithm_search_jump "ads/pkg/algorithms/search/jump"
|
||||
algorithm_search_poison "ads/pkg/algorithms/search/poison"
|
||||
algorithm_search_sequential "ads/pkg/algorithms/search/sequential"
|
||||
algorithm_stacks_next_greater_element "ads/pkg/algorithms/stacks/next_greater_element"
|
||||
algorithm_sum_maxsubsum "ads/pkg/algorithms/sum/maxsubsum"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ENDPOINT run interactive modus
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Startet App im interaktiven Modus
|
||||
func RunInteractive() error {
|
||||
logging.Plain(setup.Logo())
|
||||
_, err := menuMain.ShowMenu()
|
||||
logging.Plain("\033[2;3m...Programm terminiert.\033[0m")
|
||||
return err
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ENDPOINT run non-interactive modus
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Liest Config Datei ein und führt Algorithmen auf Fälle durch
|
||||
func RunNonInteractive(path string) error {
|
||||
var err error
|
||||
var err_case error
|
||||
|
||||
// extrahiere user config
|
||||
config := setup.NewUserConfig()
|
||||
err = setup.GetUserConfig(path, &config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
logging.Plain(setup.Logo())
|
||||
|
||||
// Fälle extrahieren
|
||||
cases := []types.UserConfigCase{}
|
||||
if config.Parts != nil && config.Parts.Cases != nil {
|
||||
cases = *config.Parts.Cases
|
||||
}
|
||||
for i := 0; i < len(cases); i++ {
|
||||
err_case = nil
|
||||
problem := cases[i]
|
||||
setup.DisplayStartOfCase(i, problem.Description)
|
||||
inputs := types.UserConfigInputs{}
|
||||
if problem.Inputs != nil {
|
||||
inputs = *problem.Inputs
|
||||
}
|
||||
if problem.Command == nil {
|
||||
err_case = fmt.Errorf("Attribute 'command:' fehlt!")
|
||||
} else {
|
||||
switch *problem.Command {
|
||||
case "algorithm-search-binary":
|
||||
L := inputs.List
|
||||
x := inputs.SearchValue
|
||||
if L != nil && x != nil {
|
||||
_, err_case = algorithm_search_binary.FancyBinarySearch(*L, *x)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-interpolation":
|
||||
L := inputs.List
|
||||
x := inputs.SearchValue
|
||||
if L != nil && x != nil {
|
||||
_, err_case = algorithm_search_interpol.FancyInterpolationSearch(*L, *x, 0, len(*L)-1)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-ith-element":
|
||||
L := inputs.List
|
||||
i := inputs.SearchRank
|
||||
if L != nil && i != nil {
|
||||
_, err_case = algorithm_search_ith_element.FancyFindIthSmallest(*L, *i)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-ith-element-dc":
|
||||
L := inputs.List
|
||||
i := inputs.SearchRank
|
||||
if L != nil && i != nil {
|
||||
_, err_case = algorithm_search_ith_element.FancyFindIthSmallestDC(*L, *i)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-jump":
|
||||
L := inputs.List
|
||||
x := inputs.SearchValue
|
||||
m := inputs.JumpSize
|
||||
if L != nil && x != nil {
|
||||
_, err_case = algorithm_search_jump.FancyJumpSearchLinear(*L, *x, *m)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-jump-exp":
|
||||
L := inputs.List
|
||||
x := inputs.SearchValue
|
||||
if L != nil && x != nil {
|
||||
_, err_case = algorithm_search_jump.FancyJumpSearchExponentiell(*L, *x)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-poison":
|
||||
L := inputs.List
|
||||
if L != nil {
|
||||
_, err_case = algorithm_search_poison.FancyFindPoison(*L)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-poison-fast":
|
||||
L := inputs.List
|
||||
if L != nil {
|
||||
_, err_case = algorithm_search_poison.FancyFindPoisonFast(*L)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-search-sequential":
|
||||
L := inputs.List
|
||||
x := inputs.SearchValue
|
||||
if L != nil && x != nil {
|
||||
_, err_case = algorithm_search_sequential.FancySequentialSearch(*L, *x)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-stacks-next-greater-element":
|
||||
L := inputs.List
|
||||
if L != nil {
|
||||
_, err_case = algorithm_stacks_next_greater_element.FancyNextGreaterElement(*L)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-sum-maxsub":
|
||||
L := inputs.List
|
||||
if L != nil {
|
||||
_, _, _, err_case = algorithm_sum_maxsubsum.FancyMaxSubSum(*L)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
case "algorithm-sum-maxsub-dc":
|
||||
L := inputs.List
|
||||
if L != nil {
|
||||
_, _, _, err_case = algorithm_sum_maxsubsum.FancyMaxSubSumDC(*L)
|
||||
} else {
|
||||
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
default:
|
||||
err_case = fmt.Errorf("Unbekannter Befehl '%[1]s'.", *problem.Command)
|
||||
}
|
||||
}
|
||||
if err_case != nil {
|
||||
logging.Error(err_case)
|
||||
}
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return nil
|
||||
}
|
254
code/golang/internal/endpoints/run/run_actions_algorithms.go
Normal file
254
code/golang/internal/endpoints/run/run_actions_algorithms.go
Normal file
@ -0,0 +1,254 @@
|
||||
package run
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/setup"
|
||||
|
||||
algorithm_search_binary "ads/pkg/algorithms/search/binary"
|
||||
algorithm_search_interpol "ads/pkg/algorithms/search/interpol"
|
||||
algorithm_search_ith_element "ads/pkg/algorithms/search/ith_element"
|
||||
algorithm_search_jump "ads/pkg/algorithms/search/jump"
|
||||
algorithm_search_poison "ads/pkg/algorithms/search/poison"
|
||||
algorithm_search_sequential "ads/pkg/algorithms/search/sequential"
|
||||
algorithm_stacks_next_greater_element "ads/pkg/algorithms/stacks/next_greater_element"
|
||||
algorithm_sum_maxsubsum "ads/pkg/algorithms/sum/maxsubsum"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ACTIONS algorithmen - search
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func actionAlgorithmSearchBinary() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{
|
||||
"muss aufsteigend sortiert sein",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_x, cancel, err := promptInputInteger("x", "Suchwert", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_binary.FancyBinarySearch(input_L, input_x)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchInterpolation() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{
|
||||
"muss aufsteigend sortiert sein",
|
||||
"sollte (idealerweise) nicht uniform verteilt sein",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_x, cancel, err := promptInputInteger("x", "Suchwert", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_interpol.FancyInterpolationSearch(input_L, input_x, 0, len(input_L)-1)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchIthElement() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_i, cancel, err := promptInputInteger("i", "Suchindex in sortierter Liste", []string{
|
||||
"sollte zw. 1 und len(L) liegen",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_ith_element.FancyFindIthSmallest(input_L, input_i)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchIthElementDc() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_i, cancel, err := promptInputInteger("i", "Suchindex in sortierter Liste", []string{
|
||||
"sollte zw. 1 und len(L) liegen",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_ith_element.FancyFindIthSmallestDC(input_L, input_i)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchJump() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{
|
||||
"muss aufsteigend sortiert sein",
|
||||
"sollte (idealerweise) nicht uniform verteilt sein",
|
||||
"sollte (idealerweise) keine Duplikate enthalten",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_x, cancel, err := promptInputInteger("x", "Suchwert", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_m, cancel, err := promptInputInteger("m", "Sprunggröße", []string{
|
||||
"sollte >= 2 sein",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_jump.FancyJumpSearchLinear(input_L, input_x, input_m)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchJumpExp() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{
|
||||
"muss aufsteigend sortiert sein",
|
||||
"sollte (idealerweise) nicht uniform verteilt sein",
|
||||
"sollte (idealerweise) keine Duplikate enthalten",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_x, cancel, err := promptInputInteger("x", "Suchwert", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_jump.FancyJumpSearchExponentiell(input_L, input_x)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchPoison() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfZeroOnes("L", "Liste von Werten", []string{
|
||||
"muss genau eine 1 enthalten",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_poison.FancyFindPoison(input_L)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchPoisonFast() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfZeroOnes("L", "Liste von Getränken", []string{
|
||||
"muss genau eine 1 enthalten",
|
||||
})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_poison.FancyFindPoisonFast(input_L)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSearchSequential() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
input_x, cancel, err := promptInputInteger("x", "Suchwert", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_search_sequential.FancySequentialSearch(input_L, input_x)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ACTIONS algorithmen - stacks
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func actionAlgorithmStacksNextGreaterElement() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, err = algorithm_stacks_next_greater_element.FancyNextGreaterElement(input_L)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ACTIONS algorithmen - sum
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func actionAlgorithmSumMaxsub() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, _, _, err = algorithm_sum_maxsubsum.FancyMaxSubSum(input_L)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
||||
|
||||
func actionAlgorithmSumMaxsubDc() (bool, error) {
|
||||
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
|
||||
if cancel || err != nil {
|
||||
return cancel, err
|
||||
}
|
||||
setup.DisplayStartOfCaseBlank()
|
||||
_, _, _, err = algorithm_sum_maxsubsum.FancyMaxSubSumDC(input_L)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
setup.DisplayEndOfCase()
|
||||
return cancel, nil
|
||||
}
|
34
code/golang/internal/endpoints/run/run_actions_basic.go
Normal file
34
code/golang/internal/endpoints/run/run_actions_basic.go
Normal file
@ -0,0 +1,34 @@
|
||||
package run
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ACTIONS - basic
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func actionShowVersion() (bool, error) {
|
||||
logging.Plain("")
|
||||
logging.Plain(setup.Logo())
|
||||
logging.Plain("Version: \033[1m%s\033[0m", setup.Version())
|
||||
logging.Plain("")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionRunOnConfig() (bool, error) {
|
||||
path, cancel, err := logging.Prompt("Pfad zur Configdatei bitte eingeben:")
|
||||
if cancel {
|
||||
return true, nil
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
err = RunNonInteractive(path)
|
||||
return false, err
|
||||
}
|
64
code/golang/internal/endpoints/run/run_actions_settings.go
Normal file
64
code/golang/internal/endpoints/run/run_actions_settings.go
Normal file
@ -0,0 +1,64 @@
|
||||
package run
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ACTIONS - settting
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func actionShowSettings() (bool, error) {
|
||||
var state string
|
||||
state = "aus"
|
||||
if logging.GetAnsiMode() {
|
||||
state = "ein"
|
||||
}
|
||||
logging.Info("Farbenmodus: %s", state)
|
||||
state = "aus"
|
||||
if logging.GetDebugMode() {
|
||||
state = "ein"
|
||||
}
|
||||
logging.Info("Debugmodus: %s", state)
|
||||
state = "aus"
|
||||
if setup.AppConfigPerformChecks() {
|
||||
state = "ein"
|
||||
}
|
||||
logging.Info("Pre/Postchecking: %s", state)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionColourModeOn() (bool, error) {
|
||||
logging.SetAnsiMode(true)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionColourModeOff() (bool, error) {
|
||||
logging.SetAnsiMode(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionDebugModeOn() (bool, error) {
|
||||
logging.SetDebugMode(true)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionDebugModeOff() (bool, error) {
|
||||
logging.SetDebugMode(false)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionPrePostCheckingOn() (bool, error) {
|
||||
setup.SetAppConfigPerformChecks(true)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func actionPrePostCheckingOff() (bool, error) {
|
||||
setup.SetAppConfigPerformChecks(false)
|
||||
return false, nil
|
||||
}
|
146
code/golang/internal/endpoints/run/run_menus.go
Normal file
146
code/golang/internal/endpoints/run/run_menus.go
Normal file
@ -0,0 +1,146 @@
|
||||
package run
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/menus"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* MENUS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var menuMain = menus.Menu{
|
||||
IsRoot: true,
|
||||
Path: []string{"Hauptmenü"},
|
||||
PromptMessages: []string{
|
||||
"Option wählen",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "Einstellungen", Submenu: &menuSettings},
|
||||
{Label: "Version des Programms anzeigen", Action: actionShowVersion},
|
||||
}, {
|
||||
{Label: "Programm auf config Datei ausführen.", Action: actionRunOnConfig},
|
||||
}, {
|
||||
{Label: "Suchalgorithmen", Submenu: &menuSearchAlgorithms},
|
||||
{Label: "Summenalgorithmen", Submenu: &menuSumAlgorithms},
|
||||
{Label: "Algorithmen mit Stacks und Queues", Submenu: &menuStacksQueuesAlgorithms},
|
||||
},
|
||||
},
|
||||
Default: -1,
|
||||
}
|
||||
|
||||
var menuSettings = menus.Menu{
|
||||
Path: []string{"Hauptmenü", "Einstellungen"},
|
||||
PromptMessages: []string{
|
||||
"Option wählen",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "Aktueller Zustand", Action: actionShowSettings},
|
||||
{Label: "Farbenmodus", Submenu: &menuColourMode},
|
||||
{Label: "Debugmodus", Submenu: &menuDebugMode},
|
||||
{Label: "Pre / Postchecking", Submenu: &menuPrePostChecking},
|
||||
},
|
||||
},
|
||||
Default: -1,
|
||||
}
|
||||
|
||||
var menuColourMode = menus.Menu{
|
||||
ForceReturn: true,
|
||||
Path: []string{"Hauptmenü", "Einstellungen", "Farbenmodus"},
|
||||
PromptMessages: []string{
|
||||
"Soll Console-Output mit Formattierung dargestellt werden?",
|
||||
"Option für den Farbenmodus wählen:",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "ein", Action: actionColourModeOn},
|
||||
{Label: "aus", Action: actionColourModeOff},
|
||||
},
|
||||
},
|
||||
Default: 1,
|
||||
}
|
||||
|
||||
var menuDebugMode = menus.Menu{
|
||||
ForceReturn: true,
|
||||
Path: []string{"Hauptmenü", "Einstellungen", "Debugmodus"},
|
||||
PromptMessages: []string{
|
||||
"Sollen Infos zu jedem Schritt der Algorithmen angezeigt werden?",
|
||||
"Option für den Debugmodus wählen:",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "ein", Action: actionDebugModeOn},
|
||||
{Label: "aus", Action: actionDebugModeOff},
|
||||
},
|
||||
},
|
||||
Default: 0,
|
||||
}
|
||||
|
||||
var menuPrePostChecking = menus.Menu{
|
||||
ForceReturn: true,
|
||||
Path: []string{"Hauptmenü", "Einstellungen", "Pre/Postchecking"},
|
||||
PromptMessages: []string{
|
||||
"Sollen Inputs+Outputs bei Algorithmenausführungen geprüft werden?",
|
||||
"Option für den Pre/Postchecking wählen:",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "ein", Action: actionPrePostCheckingOn},
|
||||
{Label: "aus", Action: actionPrePostCheckingOff},
|
||||
},
|
||||
},
|
||||
Default: 1,
|
||||
}
|
||||
|
||||
var menuSearchAlgorithms = menus.Menu{
|
||||
Path: []string{"Hauptmenü", "Suchalgorithmen"},
|
||||
PromptMessages: []string{
|
||||
"Algorithmus wählen",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "Binärsuchalgorithmus", Action: actionAlgorithmSearchBinary},
|
||||
{Label: "Interpolationsalgorithmus", Action: actionAlgorithmSearchInterpolation},
|
||||
{Label: "Suche i. kleinstes Element", Action: actionAlgorithmSearchIthElement},
|
||||
{Label: "Suche i. kleinstes Element", SubLabel: "D & C", Action: actionAlgorithmSearchIthElementDc},
|
||||
{Label: "Sprungsuche", SubLabel: "linear", Action: actionAlgorithmSearchJump},
|
||||
{Label: "Sprungsuche", SubLabel: "exponentiell", Action: actionAlgorithmSearchJumpExp},
|
||||
{Label: "Giftsuche", Action: actionAlgorithmSearchPoison},
|
||||
{Label: "Giftsuche", SubLabel: "optimiert", Action: actionAlgorithmSearchPoisonFast},
|
||||
{Label: "Sequentiellsuchalgorithmus", Action: actionAlgorithmSearchSequential},
|
||||
},
|
||||
},
|
||||
Default: -1,
|
||||
}
|
||||
|
||||
var menuStacksQueuesAlgorithms = menus.Menu{
|
||||
Path: []string{"Hauptmenü", "Algorithmen mit Stacks und Queues"},
|
||||
PromptMessages: []string{
|
||||
"Algorithmus wählen",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "'Next Greater Element' mit Stacks", Action: actionAlgorithmStacksNextGreaterElement},
|
||||
},
|
||||
},
|
||||
Default: -1,
|
||||
}
|
||||
|
||||
var menuSumAlgorithms = menus.Menu{
|
||||
Path: []string{"Hauptmenü", "Summenalgorithmen"},
|
||||
PromptMessages: []string{
|
||||
"Algorithmus wählen",
|
||||
},
|
||||
Options: [][]menus.MenuOption{
|
||||
{
|
||||
{Label: "Maximale Teilsumme", SubLabel: "brute force", Action: actionAlgorithmSumMaxsub},
|
||||
{Label: "Maximale Teilsumme", SubLabel: "D & C", Action: actionAlgorithmSumMaxsubDc},
|
||||
},
|
||||
},
|
||||
Default: -1,
|
||||
}
|
76
code/golang/internal/endpoints/run/run_prompts.go
Normal file
76
code/golang/internal/endpoints/run/run_prompts.go
Normal file
@ -0,0 +1,76 @@
|
||||
package run
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/menus"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CUSTOM PROMPTS für besondere Inputs
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func promptInputInteger(name string, descr string, requirements []string) (int, bool, error) {
|
||||
type responseType struct {
|
||||
Response int `yaml:"response"`
|
||||
}
|
||||
var response = responseType{}
|
||||
var query = menus.PromptValueQuery{
|
||||
Description: descr,
|
||||
Name: name,
|
||||
Type: "Integer",
|
||||
Requirements: &requirements,
|
||||
Response: &response,
|
||||
}
|
||||
cancel, err := query.Prompt()
|
||||
return response.Response, cancel, err
|
||||
}
|
||||
|
||||
func promptInputListOfInt(name string, descr string, requirements []string) ([]int, bool, error) {
|
||||
type responseType struct {
|
||||
Response []int `yaml:"response"`
|
||||
}
|
||||
var response = responseType{}
|
||||
var query = menus.PromptValueQuery{
|
||||
Description: descr,
|
||||
Name: name,
|
||||
Type: "Integerliste",
|
||||
ValidExamples: &[]string{
|
||||
"[1, 2, 7, 8, 5]",
|
||||
"[1000, 0, 4]",
|
||||
},
|
||||
Requirements: &requirements,
|
||||
Response: &response,
|
||||
}
|
||||
cancel, err := query.Prompt()
|
||||
return response.Response, cancel, err
|
||||
}
|
||||
|
||||
func promptInputListOfZeroOnes(name string, descr string, requirements []string) ([]int, bool, error) {
|
||||
var values = []int{}
|
||||
type responseType struct {
|
||||
Response []uint8 `yaml:"response"`
|
||||
}
|
||||
var response = responseType{}
|
||||
var query = menus.PromptValueQuery{
|
||||
Description: descr,
|
||||
Name: name,
|
||||
Type: "Liste von 0er und 1er",
|
||||
ValidExamples: &[]string{
|
||||
"[0, 0, 0, 1, 0]",
|
||||
"[1, 0, 1, 1]",
|
||||
},
|
||||
Requirements: &requirements,
|
||||
Response: &response,
|
||||
}
|
||||
cancel, err := query.Prompt()
|
||||
// uint8 -> int
|
||||
if response.Response != nil {
|
||||
for _, x := range response.Response {
|
||||
values = append(values, int(x))
|
||||
}
|
||||
}
|
||||
return values, cancel, err
|
||||
}
|
206
code/golang/internal/menus/menus.go
Normal file
206
code/golang/internal/menus/menus.go
Normal file
@ -0,0 +1,206 @@
|
||||
package menus
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"ads/internal/core/logging"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD menu class methods
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func (menu *Menu) SetDefault(index int) {
|
||||
menu.Default = index
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD show menu
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func (menu Menu) ShowMenu() (bool, error) {
|
||||
var (
|
||||
choice string
|
||||
index int
|
||||
meta bool
|
||||
quit bool
|
||||
cancel bool
|
||||
err error
|
||||
)
|
||||
var promptMessages []string
|
||||
var optionsFlattened []MenuOption
|
||||
var optionsKeyValue [][2]string
|
||||
var defaultOption string
|
||||
var breaks []int
|
||||
|
||||
// Headline einfügen
|
||||
promptMessages = make([]string, len(menu.PromptMessages))
|
||||
copy(promptMessages, menu.PromptMessages)
|
||||
head := fmt.Sprintf("\033[2m%s\033[0m", strings.Join(menu.Path, " > "))
|
||||
promptMessages = append([]string{head}, promptMessages...)
|
||||
|
||||
// Zurück-Option einfügen
|
||||
defaultOption = ""
|
||||
if menu.Default >= 0 {
|
||||
defaultOption = fmt.Sprintf("%v", menu.Default+1)
|
||||
}
|
||||
breaks = []int{}
|
||||
optionsFlattened = []MenuOption{}
|
||||
optionsKeyValue = []([2]string){}
|
||||
index = 0
|
||||
for _, suboptions := range menu.Options {
|
||||
for _, opt := range suboptions {
|
||||
optionsFlattened = append(optionsFlattened, opt)
|
||||
key := fmt.Sprintf("%v", index+1)
|
||||
subLabel := opt.SubLabel
|
||||
label := opt.Label
|
||||
if !(subLabel == "") {
|
||||
label = fmt.Sprintf("%v (\033[2m%v\033[0m)", opt.Label, subLabel)
|
||||
}
|
||||
optionsKeyValue = append(optionsKeyValue, [2]string{key, label})
|
||||
index++
|
||||
}
|
||||
breaks = append(breaks, index-1)
|
||||
}
|
||||
if !menu.IsRoot {
|
||||
optionsKeyValue = append(optionsKeyValue, [2]string{"z", "Zurück zum vorherigen Menü"})
|
||||
}
|
||||
optionsKeyValue = append(optionsKeyValue, [2]string{"q", "Programm schließen"})
|
||||
|
||||
// User Response immer abfragen und abarbeiten, bis quit/return.
|
||||
performClearScreen := !menu.IsRoot
|
||||
for {
|
||||
if performClearScreen {
|
||||
logging.ClearScreen()
|
||||
}
|
||||
performClearScreen = true
|
||||
|
||||
choice, meta = promptListOfOptions(promptMessages, optionsKeyValue, breaks, defaultOption)
|
||||
|
||||
// Falls quit wählt, -> quit:
|
||||
if (menu.IsRoot && meta) || choice == "q" {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Falls User back wählt, -> return:
|
||||
if (!menu.IsRoot && meta) || choice == "z" {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// sonst führe die assoziierte Methode aus
|
||||
index64, _ := strconv.ParseInt(choice, 10, 64)
|
||||
index = int(index64) - 1
|
||||
if 0 <= index && index < len(optionsFlattened) {
|
||||
opt := optionsFlattened[index]
|
||||
// Entweder Untermenü öffnen oder Action ausführen
|
||||
if opt.Submenu != nil {
|
||||
quit, err = opt.Submenu.ShowMenu()
|
||||
if quit {
|
||||
return true, err
|
||||
}
|
||||
} else if opt.Action != nil {
|
||||
cancel, err = opt.Action()
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
}
|
||||
// Falls ForceReturn, dann nach Ausführung der Action, -> return
|
||||
if menu.ForceReturn {
|
||||
return false, nil
|
||||
} else {
|
||||
// Falls während der Action der User Meta+D klickt, -> return:
|
||||
if cancel {
|
||||
continue
|
||||
}
|
||||
quit := logging.PromptAnyKeyToContinue()
|
||||
// Falls nach der Action der User Meta+D klickt, -> quit:
|
||||
if quit {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
} else {
|
||||
logging.Warn("Option noch nicht implementiert.")
|
||||
quit := logging.PromptAnyKeyToContinue()
|
||||
if quit {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD prompt values
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func (query *PromptValueQuery) Prompt() (bool, error) {
|
||||
var lines = []interface{}{}
|
||||
var responsePtr = query.Response
|
||||
var (
|
||||
line string
|
||||
cancel bool
|
||||
err error
|
||||
)
|
||||
|
||||
// prüfen, dass response ein Ptr auf eine Struct ist:
|
||||
if !(reflect.ValueOf(responsePtr).Kind() == reflect.Ptr) || !(reflect.ValueOf(responsePtr).Elem().Kind() == reflect.Struct) {
|
||||
panic("Input muss ein Pointer auf einen struct sein")
|
||||
}
|
||||
|
||||
// prompt message vorbereiten:
|
||||
lines = append(lines, fmt.Sprintf("%s, \033[1;3m%s\033[0m, als \033[1m%s\033[0m bitte eingeben.", query.Description, query.Name, query.Type))
|
||||
if query.ValidExamples != nil && len(*query.ValidExamples) > 0 {
|
||||
if len(*query.ValidExamples) == 1 {
|
||||
example := (*query.ValidExamples)[0]
|
||||
lines = append(lines, fmt.Sprintf(" \033[3;4mBeispiel von Input im gültigen Format:\033[0m \033[2m%s\033[0m", example))
|
||||
} else {
|
||||
lines = append(lines, fmt.Sprintf(" \033[3;4mBeispiele von Inputs im gültigen Format:\033[0m"))
|
||||
for _, example := range *query.ValidExamples {
|
||||
lines = append(lines, fmt.Sprintf(" - \033[2m%s\033[0m", example))
|
||||
}
|
||||
lines = append(lines, fmt.Sprintf(" - \033[2;3metc.\033[0m"))
|
||||
}
|
||||
}
|
||||
if query.Requirements != nil && len(*query.Requirements) > 0 {
|
||||
if len(*query.Requirements) == 1 {
|
||||
requirement := (*query.Requirements)[0]
|
||||
lines = append(lines, fmt.Sprintf(" \033[3;4mAnforderung(en) auf Input:\033[0m \033[2m%s\033[0m", requirement))
|
||||
} else {
|
||||
lines = append(lines, fmt.Sprintf(" \033[3;4mAnforderung(en) auf Input:\033[0m"))
|
||||
for _, requirement := range *query.Requirements {
|
||||
lines = append(lines, fmt.Sprintf(" - \033[2m%s\033[0m", requirement))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// prompt Eingabe eines Werts:
|
||||
for {
|
||||
line, cancel, err = logging.Prompt(lines...)
|
||||
if cancel {
|
||||
return true, nil
|
||||
}
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
logging.Plain("")
|
||||
continue
|
||||
}
|
||||
line = fmt.Sprintf("\"response\": %s", line)
|
||||
err = yaml.Unmarshal([]byte(line), query.Response)
|
||||
if err != nil {
|
||||
logging.Error(err)
|
||||
logging.Plain("")
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
return cancel, err
|
||||
}
|
81
code/golang/internal/menus/menus_prompt.go
Normal file
81
code/golang/internal/menus/menus_prompt.go
Normal file
@ -0,0 +1,81 @@
|
||||
package menus
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD prompt options
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Zeigt Prompt mit Liste von Optionen an
|
||||
func promptListOfOptions(messages []string, options [][2]string, breaks []int, defaultChoice string) (string, bool) {
|
||||
var n = len(options)
|
||||
var (
|
||||
choice string
|
||||
cancel bool
|
||||
err error
|
||||
)
|
||||
var lines []interface{}
|
||||
var optionsMap = map[string]string{}
|
||||
|
||||
// Erzeuge Messages
|
||||
lines = []interface{}{}
|
||||
for _, message := range messages {
|
||||
lines = append(lines, message)
|
||||
}
|
||||
lines = append(lines, "")
|
||||
textbar := fmt.Sprintf(" \033[93m+%s+\033[0m", strings.Repeat("-", 40))
|
||||
lines = append(lines, textbar)
|
||||
for i, obj := range options {
|
||||
key := obj[0]
|
||||
label := obj[1]
|
||||
optionsMap[key] = label
|
||||
if key == defaultChoice {
|
||||
lines = append(lines, fmt.Sprintf("\033[91m*\033[0m\033[93;1m%v)\033[0m %v", key, label))
|
||||
} else {
|
||||
lines = append(lines, fmt.Sprintf(" \033[93;1m%v)\033[0m %v", key, label))
|
||||
}
|
||||
if i < n-1 && utils.ArrayContains(breaks, i) {
|
||||
lines = append(lines, " \033[93m+----\033[0m")
|
||||
}
|
||||
i++
|
||||
}
|
||||
lines = append(lines, textbar)
|
||||
if !(defaultChoice == "") {
|
||||
lines = append(lines, "")
|
||||
lines = append(lines, " \033[91;2m*\033[0m\033[2m = Default\033[0m")
|
||||
}
|
||||
|
||||
// Wiederhole Prompt, bis gültige Eingabe erreicht
|
||||
for {
|
||||
choice, cancel, err = logging.Prompt(lines...)
|
||||
if cancel {
|
||||
return "", true
|
||||
}
|
||||
if err != nil {
|
||||
logging.ClearScreen()
|
||||
logging.Error(err)
|
||||
continue
|
||||
}
|
||||
if choice == "" {
|
||||
choice = defaultChoice
|
||||
break
|
||||
}
|
||||
if _, ok := optionsMap[choice]; !ok {
|
||||
logging.ClearScreen()
|
||||
logging.Error("Ungültige eingabe")
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return choice, false
|
||||
}
|
58
code/golang/internal/menus/menus_type.go
Normal file
58
code/golang/internal/menus/menus_type.go
Normal file
@ -0,0 +1,58 @@
|
||||
package menus
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type MenuOption struct {
|
||||
Label string
|
||||
SubLabel string
|
||||
Submenu *Menu
|
||||
Action func() (bool, error) // NOTE: in go, this is automatically a pointer type
|
||||
}
|
||||
|
||||
type Menu struct {
|
||||
IsRoot bool
|
||||
ForceReturn bool
|
||||
Path []string
|
||||
PromptMessages []string
|
||||
Options [][]MenuOption
|
||||
Default int
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPES - prompt
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Usage
|
||||
|
||||
- Name: Variablenname
|
||||
|
||||
- Description: Kurze Beschreibung der Variablen
|
||||
|
||||
- Type: Beschreiben des erwarteten Types der Variablen.
|
||||
|
||||
- Requirements: Liste von Anforderungen.
|
||||
|
||||
- Response: Ptr zur Struct, d. h. &responseType{}, wobei responseType eine struct der folgenden Form ist:
|
||||
|
||||
type responseType struct { Response #### `yaml:"response"` }
|
||||
|
||||
wobei #### = ein Typ
|
||||
*/
|
||||
type PromptValueQuery struct {
|
||||
Name string
|
||||
Description string
|
||||
Type string
|
||||
ValidExamples *[]string
|
||||
Requirements *[]string
|
||||
// Response muss ein Ptr auf eine Struct sein:
|
||||
Response interface{}
|
||||
}
|
94
code/golang/internal/setup/cli/cli.go
Normal file
94
code/golang/internal/setup/cli/cli.go
Normal file
@ -0,0 +1,94 @@
|
||||
package cli
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/akamensky/argparse"
|
||||
|
||||
"ads/internal/types"
|
||||
"ads/pkg/re"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var Parser *argparse.Parser
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* LOCAL VARIABLES / CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var optionsQuiet = argparse.Options{
|
||||
Help: "Blendet alle Konsole-Messages aus.",
|
||||
Required: false,
|
||||
Default: false,
|
||||
}
|
||||
|
||||
var optionsChecks = argparse.Options{
|
||||
Help: "Ob vor und nach Ausführung von Algorithmen Checks auf Inputs/Outputs ausgeführt werden sollen.",
|
||||
Required: false,
|
||||
// NOTE: no `Boolean` option available!
|
||||
Default: "false",
|
||||
}
|
||||
|
||||
var optionsDebug = argparse.Options{
|
||||
Help: "Blendet Debugging-Befehle ein.",
|
||||
Required: false,
|
||||
Default: false,
|
||||
}
|
||||
|
||||
var optionsInteractive = argparse.Options{
|
||||
Help: "Startet das Programm im interaktiven Modus.",
|
||||
Required: false,
|
||||
Default: false,
|
||||
}
|
||||
|
||||
var optionsColour = argparse.Options{
|
||||
Help: "Ob Logging färblich angezeigt wird.",
|
||||
Required: false,
|
||||
// NOTE: no `Boolean` option available!
|
||||
Default: "false",
|
||||
}
|
||||
|
||||
var optionsConfigFile = argparse.Options{
|
||||
Help: "Pfad zur Configdatei (nur für run Endpunkt).",
|
||||
Required: false,
|
||||
Default: "code/config.yml",
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS parse cli
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Parst cli flags.
|
||||
func ParseCli(args []string) (*types.CliArguments, error) {
|
||||
var err error
|
||||
Parser = argparse.NewParser(
|
||||
"cli parser",
|
||||
"\033[93;2mEin Programm zur Ausführung verschiedener Algorithmen aus dem Kurs AlgoDat I.\033[0m",
|
||||
)
|
||||
arguments := types.CliArguments{
|
||||
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),
|
||||
Checks: Parser.String("", "checks", &optionsChecks),
|
||||
Colour: Parser.String("", "colour", &optionsColour),
|
||||
ConfigFile: Parser.String("", "config", &optionsConfigFile),
|
||||
}
|
||||
err = Parser.Parse(args)
|
||||
return &arguments, err
|
||||
}
|
||||
|
||||
// Prüft, ob der Parser nur deshalb fehlschlägt, weil ein Command fehlt.
|
||||
func ParseCliCommandMissing(err error) bool {
|
||||
// FIXME: unschöne Lösung. Leider ist Error-Typ im Package versteckt
|
||||
return re.Matches(`(?i)(command required)`, fmt.Sprintf("%v", err))
|
||||
}
|
56
code/golang/internal/setup/setup_appconfig.go
Normal file
56
code/golang/internal/setup/setup_appconfig.go
Normal file
@ -0,0 +1,56 @@
|
||||
package setup
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"ads/internal/types"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var AppConfig = types.AppConfig{}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS getters
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Extrahiert Inhalte einer YAML Config und parset dies als Struktur
|
||||
func AppConfigInitialise() error {
|
||||
contents := AppConfigYaml()
|
||||
err := yaml.Unmarshal([]byte(contents), &AppConfig)
|
||||
return err
|
||||
}
|
||||
|
||||
func AppConfigFancyMode() bool {
|
||||
return AppConfig.Options.Display
|
||||
}
|
||||
|
||||
func AppConfigShowMetrics() bool {
|
||||
return AppConfig.Options.Metrics
|
||||
}
|
||||
|
||||
func AppConfigPerformChecks() bool {
|
||||
return AppConfig.Options.Checks
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS setters
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func SetAppConfigFancyMode(value bool) {
|
||||
AppConfig.Options.Display = value
|
||||
}
|
||||
|
||||
func SetAppConfigShowMetrics(value bool) {
|
||||
AppConfig.Options.Metrics = value
|
||||
}
|
||||
|
||||
func SetAppConfigPerformChecks(value bool) {
|
||||
AppConfig.Options.Checks = value
|
||||
}
|
60
code/golang/internal/setup/setup_assets.go
Normal file
60
code/golang/internal/setup/setup_assets.go
Normal file
@ -0,0 +1,60 @@
|
||||
package setup
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"fmt"
|
||||
"log"
|
||||
"strings"
|
||||
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var Res embed.FS
|
||||
var Assets map[string]string
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD read assets
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func ReadAsset(key string) string {
|
||||
var found bool
|
||||
if _, found = Assets[key]; !found {
|
||||
log.Fatal(fmt.Sprintf("Key \033[1m%s\033[0m not found in dictionary!", key))
|
||||
}
|
||||
data, err := Res.ReadFile(Assets[key])
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
text := string(data)
|
||||
return text
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS assets
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func Help() string {
|
||||
contents := ReadAsset("help")
|
||||
return utils.DedentAndExpand(contents)
|
||||
}
|
||||
|
||||
func Logo() string {
|
||||
contents := ReadAsset("logo")
|
||||
return utils.DedentAndExpand(contents)
|
||||
}
|
||||
|
||||
func Version() string {
|
||||
return strings.Trim(ReadAsset("version"), "\n")
|
||||
}
|
||||
|
||||
func AppConfigYaml() string {
|
||||
return strings.Trim(ReadAsset("appconfig"), "\n")
|
||||
}
|
130
code/golang/internal/setup/setup_display.go
Normal file
130
code/golang/internal/setup/setup_display.go
Normal file
@ -0,0 +1,130 @@
|
||||
package setup
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD display case start/end
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func DisplayStartOfCase(index int, descr *string) {
|
||||
DisplayBar(80)
|
||||
if descr == nil || *descr == "" {
|
||||
logging.Plain("\033[92;1mCASE %[1]v\033[0m.", index)
|
||||
} else {
|
||||
logging.Plain("\033[92;1mCASE %[1]v\033[0m (\033[1;2m%[2]s\033[0m).", index, *descr)
|
||||
}
|
||||
}
|
||||
|
||||
func DisplayStartOfCaseBlank() {
|
||||
DisplayBar(80)
|
||||
return
|
||||
}
|
||||
|
||||
func DisplayEndOfCase() {
|
||||
DisplayBar(80)
|
||||
return
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD display value
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func RepresentValue(value interface{}) interface{} {
|
||||
switch reflect.TypeOf(value).Kind() {
|
||||
case reflect.Ptr:
|
||||
obj := reflect.ValueOf(value)
|
||||
if obj.IsNil() {
|
||||
return fmt.Sprintf("%v", nil)
|
||||
} else {
|
||||
return fmt.Sprintf("&%v", RepresentValue(obj.Elem().Interface()))
|
||||
}
|
||||
case reflect.Slice:
|
||||
obj := reflect.ValueOf(value)
|
||||
n := obj.Len()
|
||||
values := []interface{}{}
|
||||
for i := 0; i < n; i++ {
|
||||
x := RepresentValue(obj.Index(i).Interface())
|
||||
values = append(values, x)
|
||||
}
|
||||
if n > 10 {
|
||||
values = append(append(values[:3], "..."), values[n-2:]...)
|
||||
}
|
||||
return fmt.Sprintf("%v", values)
|
||||
case reflect.Map:
|
||||
obj := reflect.ValueOf(value)
|
||||
n := obj.Len()
|
||||
iter := obj.MapRange()
|
||||
m := map[interface{}]interface{}{}
|
||||
parts := []string{}
|
||||
for iter.Next() {
|
||||
key := iter.Key().Interface()
|
||||
x := RepresentValue(iter.Value().Interface())
|
||||
m[key] = x
|
||||
parts = append(parts, fmt.Sprintf("%[1]v: %[2]v", key, x))
|
||||
}
|
||||
if n > 4 {
|
||||
parts = append(append(parts[:3], "..."), parts[n-2:]...)
|
||||
}
|
||||
return fmt.Sprintf("{%s}", strings.Join(parts, ", "))
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD display algorithm start/end
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func DisplayStartOfAlgorithm(name string, inputs map[string]interface{}) {
|
||||
logging.Plain("Ausführung vom Algorithmus: \033[92;1m%[1]s\033[0m", name)
|
||||
logging.Plain("INPUTS")
|
||||
for varname, value := range inputs {
|
||||
logging.Plain(" - %[1]s = %[2]v", varname, RepresentValue(value))
|
||||
}
|
||||
}
|
||||
|
||||
func DisplayEndOfAlgorithm(outputs map[string]interface{}) {
|
||||
logging.Plain("OUTPUTS:")
|
||||
for varname, value := range outputs {
|
||||
logging.Plain(" - %[1]s = %[2]v", varname, RepresentValue(value))
|
||||
}
|
||||
}
|
||||
|
||||
func DisplayMetrics() {
|
||||
// logging.Plain("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsed())
|
||||
logging.Plain("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsedLongFormat())
|
||||
logging.Plain("Kosten (Zeit): T(n) = \033[1m%[1]v\033[0m", displayCost(metrics.GetTimeCost()))
|
||||
logging.Plain("Kosten (#Züge): M(n) = \033[1m%[1]v\033[0m", displayCost(metrics.GetMovesCost()))
|
||||
logging.Plain("Kosten (Platz): S(n) = \033[1m%[1]v\033[0m", displayCost(metrics.GetSpaceCost()))
|
||||
return
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS Verschiedenes
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func DisplayBar(options ...int) {
|
||||
n := 80
|
||||
if len(options) > 0 {
|
||||
n = options[0]
|
||||
}
|
||||
logging.Plain("+%[1]s+", strings.Repeat("-", n))
|
||||
return
|
||||
}
|
||||
|
||||
func displayCost(cost int) string {
|
||||
if cost > 0 {
|
||||
return fmt.Sprintf("%v", cost)
|
||||
}
|
||||
return "-"
|
||||
}
|
31
code/golang/internal/setup/setup_userconfig.go
Normal file
31
code/golang/internal/setup/setup_userconfig.go
Normal file
@ -0,0 +1,31 @@
|
||||
package setup
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
|
||||
"ads/internal/types"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
// Erstellt eine Struktur, die die Infos aus der Config-Datei erfasst
|
||||
func NewUserConfig() types.UserConfig {
|
||||
return types.UserConfig{}
|
||||
}
|
||||
|
||||
// Extrahiert Inhalte einer YAML Config und parset dies als Struktur
|
||||
func GetUserConfig(path string, config *types.UserConfig) error {
|
||||
contents, err := ioutil.ReadFile(path)
|
||||
if err == nil {
|
||||
err = yaml.Unmarshal(contents, config)
|
||||
}
|
||||
return err
|
||||
}
|
27
code/golang/internal/types/types_appconfig.go
Normal file
27
code/golang/internal/types/types_appconfig.go
Normal file
@ -0,0 +1,27 @@
|
||||
package types
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* YAML SCHEMES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type AppConfig struct {
|
||||
Info *AppConfigInfo `yaml:"info"`
|
||||
Options *AppConfigOptions `yaml:"options"`
|
||||
}
|
||||
|
||||
type AppConfigInfo struct {
|
||||
Title *string `yaml:"title"`
|
||||
Description *string `yaml:"description"`
|
||||
}
|
||||
|
||||
type AppConfigOptions struct {
|
||||
Display bool `yaml:"display"`
|
||||
Checks bool `yaml:"checks"`
|
||||
Metrics bool `yaml:"metrics"`
|
||||
}
|
109
code/golang/internal/types/types_basic.go
Normal file
109
code/golang/internal/types/types_basic.go
Normal file
@ -0,0 +1,109 @@
|
||||
package types
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD convert basic types to pointers
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/****
|
||||
* NOTE: these cannot be replaced by inline variants, e.g.
|
||||
* var x string
|
||||
* var xx *string = &x
|
||||
* as then the values are tied.
|
||||
* These methods create addresses to clones of the original variables,
|
||||
* and do not coincide with the addresses of the original variables.
|
||||
****/
|
||||
|
||||
func StructToPtr(x struct{}) *struct{} {
|
||||
var value = x
|
||||
return &value
|
||||
}
|
||||
|
||||
func InterfaceToPtr(x interface{}) *interface{} {
|
||||
var value = x
|
||||
return &value
|
||||
}
|
||||
|
||||
func BoolToPtr(x bool) *bool {
|
||||
var value = x
|
||||
return &value
|
||||
}
|
||||
|
||||
func StringToPtr(x string) *string {
|
||||
var value = x
|
||||
return &value
|
||||
}
|
||||
|
||||
func IntToPtr(x int) *int {
|
||||
var value = x
|
||||
return &value
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD get value from ptr with default
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func ExpandPtrToBool(p *bool) interface{} {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func PtrToBool(p *bool, Default bool) bool {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return Default
|
||||
}
|
||||
|
||||
func ExpandPtrToString(p *string) interface{} {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func PtrToString(p *string, Default string) string {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return Default
|
||||
}
|
||||
|
||||
func ExpandPtrToInt(p *int) interface{} {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
func PtrToInt(p *int, Default int) int {
|
||||
if p != nil {
|
||||
return *p
|
||||
}
|
||||
return Default
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD interface to (ptr to) array
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func InterfaceToArray(x interface{}) *[]interface{} {
|
||||
if reflect.TypeOf(x).Kind() == reflect.Slice {
|
||||
var xSlice []interface{} = []interface{}{}
|
||||
var xConverted = reflect.ValueOf(x)
|
||||
for i := 0; i < xConverted.Len(); i++ {
|
||||
xSlice = append(xSlice, xConverted.Index(i).Interface())
|
||||
}
|
||||
return &xSlice
|
||||
}
|
||||
return nil
|
||||
}
|
55
code/golang/internal/types/types_cli.go
Normal file
55
code/golang/internal/types/types_cli.go
Normal file
@ -0,0 +1,55 @@
|
||||
package types
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"github.com/akamensky/argparse"
|
||||
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type CliArguments struct {
|
||||
ModeHelp *argparse.Command
|
||||
ModeVersion *argparse.Command
|
||||
ModeRun *argparse.Command
|
||||
Quiet *bool
|
||||
Debug *bool
|
||||
Interactive *bool
|
||||
Checks *string
|
||||
Colour *string
|
||||
ConfigFile *string
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS convert string option to boolean
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func (arguments CliArguments) QuietModeOn() bool {
|
||||
return *arguments.Quiet
|
||||
}
|
||||
|
||||
func (arguments CliArguments) DebugModeOn() bool {
|
||||
return *arguments.Debug
|
||||
}
|
||||
|
||||
func (arguments CliArguments) InteractiveMode() bool {
|
||||
return *arguments.Interactive
|
||||
}
|
||||
|
||||
func (arguments CliArguments) ShowChecks() bool {
|
||||
return !utils.IsFalse(*arguments.Checks)
|
||||
}
|
||||
|
||||
func (arguments CliArguments) ShowColour() bool {
|
||||
return !utils.IsFalse(*arguments.Colour)
|
||||
}
|
||||
|
||||
func (arguments CliArguments) GetConfigFile() string {
|
||||
return *arguments.ConfigFile
|
||||
}
|
56
code/golang/internal/types/types_counter.go
Normal file
56
code/golang/internal/types/types_counter.go
Normal file
@ -0,0 +1,56 @@
|
||||
package types
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPE Counter
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type Counter struct {
|
||||
nr int
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CLASS METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func NewCounter() Counter {
|
||||
c := Counter{}
|
||||
return c
|
||||
}
|
||||
|
||||
func (self Counter) String() string {
|
||||
return fmt.Sprintf("%[1]v", self.nr)
|
||||
}
|
||||
|
||||
func (self Counter) Size() int {
|
||||
return self.nr
|
||||
}
|
||||
|
||||
func (self *Counter) Reset() {
|
||||
self.nr = 0
|
||||
}
|
||||
|
||||
func (self *Counter) Set(n int) {
|
||||
self.nr = n
|
||||
}
|
||||
|
||||
func (self *Counter) Add(options ...int) {
|
||||
n := 1
|
||||
if len(options) > 0 {
|
||||
n = options[0]
|
||||
}
|
||||
self.nr += n
|
||||
}
|
72
code/golang/internal/types/types_timer.go
Normal file
72
code/golang/internal/types/types_timer.go
Normal file
@ -0,0 +1,72 @@
|
||||
package types
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPE Timer
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type Timer struct {
|
||||
time_elapsed time.Duration
|
||||
time_current time.Time
|
||||
running bool
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CLASS METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func NewTimer() Timer {
|
||||
c := Timer{}
|
||||
c.Reset()
|
||||
return c
|
||||
}
|
||||
|
||||
func (self Timer) String() string {
|
||||
return fmt.Sprintf("%[1]v", self.time_elapsed)
|
||||
}
|
||||
|
||||
func (self Timer) CurrentTime() time.Time {
|
||||
return self.time_current
|
||||
}
|
||||
|
||||
func (self Timer) ElapsedTime() time.Duration {
|
||||
return self.time_elapsed
|
||||
}
|
||||
|
||||
func (self *Timer) Start() {
|
||||
self.time_current = time.Now()
|
||||
self.running = true
|
||||
}
|
||||
|
||||
func (self *Timer) Stop() {
|
||||
if self.running {
|
||||
t0 := self.time_current
|
||||
t1 := time.Now()
|
||||
delta := t1.Sub(t0)
|
||||
self.time_current = t1
|
||||
self.time_elapsed += delta
|
||||
}
|
||||
self.running = false
|
||||
}
|
||||
|
||||
func (self *Timer) Reset() {
|
||||
t := time.Now()
|
||||
delta := t.Sub(t) // d. h. 0
|
||||
self.time_current = t
|
||||
self.time_elapsed = delta
|
||||
self.running = false
|
||||
}
|
38
code/golang/internal/types/types_userconfig.go
Normal file
38
code/golang/internal/types/types_userconfig.go
Normal file
@ -0,0 +1,38 @@
|
||||
package types
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* YAML SCHEMES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type UserConfig struct {
|
||||
Info *UserConfigInfo `yaml:"info"`
|
||||
Parts *UserConfigParts `yaml:"parts"`
|
||||
}
|
||||
|
||||
type UserConfigInfo struct {
|
||||
Title *string `yaml:"title"`
|
||||
Description *string `yaml:"description"`
|
||||
}
|
||||
|
||||
type UserConfigParts struct {
|
||||
Cases *([]UserConfigCase) `yaml:"cases"`
|
||||
}
|
||||
|
||||
type UserConfigCase struct {
|
||||
Command *string `yaml:"command"`
|
||||
Description *string `yaml:"description"`
|
||||
Inputs *UserConfigInputs `yaml:"inputs"`
|
||||
}
|
||||
|
||||
type UserConfigInputs struct {
|
||||
List *[]int `yaml:"L"`
|
||||
SearchRank *int `yaml:"i"`
|
||||
SearchValue *int `yaml:"x"`
|
||||
JumpSize *int `yaml:"m"`
|
||||
}
|
103
code/golang/main.go
Normal file
103
code/golang/main.go
Normal file
@ -0,0 +1,103 @@
|
||||
package main
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"embed"
|
||||
"os"
|
||||
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/setup"
|
||||
"ads/internal/setup/cli"
|
||||
"ads/internal/types"
|
||||
|
||||
endpoints_print "ads/internal/endpoints/print"
|
||||
endpoints_run "ads/internal/endpoints/run"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
var (
|
||||
// !!! NOTE: do not remove the following "comment", as it is a preprocessing instruction !!!
|
||||
//go:embed assets/*
|
||||
res embed.FS
|
||||
assets = map[string]string{
|
||||
"appconfig": "assets/config.yml",
|
||||
"version": "assets/VERSION",
|
||||
"logo": "assets/LOGO",
|
||||
"help": "assets/HELP",
|
||||
}
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD main
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func main() {
|
||||
var arguments *types.CliArguments
|
||||
var (
|
||||
err1 error
|
||||
err2 error
|
||||
err3 error
|
||||
cmdMissing bool
|
||||
showChecks bool
|
||||
)
|
||||
|
||||
// assets festlegen
|
||||
setup.Res = res
|
||||
setup.Assets = assets
|
||||
|
||||
// cli arguments parsen
|
||||
arguments, err1 = cli.ParseCli(os.Args)
|
||||
cmdMissing = cli.ParseCliCommandMissing(err1)
|
||||
|
||||
// Programmeinstellungen initialisieren
|
||||
showChecks = false
|
||||
if err1 == nil {
|
||||
if !(arguments.ModeRun.Happened() && arguments.InteractiveMode()) {
|
||||
logging.SetQuietMode(arguments.QuietModeOn())
|
||||
logging.SetDebugMode(arguments.DebugModeOn())
|
||||
}
|
||||
logging.SetAnsiMode(arguments.ShowColour())
|
||||
showChecks = arguments.ShowChecks()
|
||||
}
|
||||
err2 = setup.AppConfigInitialise()
|
||||
setup.SetAppConfigPerformChecks(showChecks)
|
||||
|
||||
// Fehler melden (fatal)
|
||||
if err1 != nil && !cmdMissing {
|
||||
logging.Fatal(err1)
|
||||
}
|
||||
if err2 != nil {
|
||||
logging.Fatal(err2)
|
||||
}
|
||||
// Wenn der Artefakt ohne Argument aufgerufen wird, keinen Fehler melden, sondern im it-Modus ausführen
|
||||
if cmdMissing {
|
||||
endpoints_run.RunInteractive()
|
||||
return
|
||||
}
|
||||
// Sonst Commands behandeln
|
||||
if arguments.ModeHelp.Happened() {
|
||||
endpoints_print.Help()
|
||||
return
|
||||
} else if arguments.ModeVersion.Happened() {
|
||||
endpoints_print.Version()
|
||||
return
|
||||
} else if arguments.ModeRun.Happened() {
|
||||
if arguments.InteractiveMode() {
|
||||
endpoints_run.RunInteractive()
|
||||
} else {
|
||||
err3 = endpoints_run.RunNonInteractive(arguments.GetConfigFile())
|
||||
if err3 != nil {
|
||||
logging.Fatal(err3)
|
||||
}
|
||||
}
|
||||
return
|
||||
} else {
|
||||
endpoints_run.RunInteractive()
|
||||
}
|
||||
}
|
54
code/golang/pkg/algorithms/search/binary/binary.go
Normal file
54
code/golang/pkg/algorithms/search/binary/binary.go
Normal file
@ -0,0 +1,54 @@
|
||||
package binary
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM binary search
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func BinarySearch(L []int, x int) int {
|
||||
if len(L) == 0 {
|
||||
logging.Debug("x nicht in L.")
|
||||
return -1
|
||||
}
|
||||
metrics.AddTimeCost()
|
||||
m := int(len(L) / 2)
|
||||
if L[m] == x {
|
||||
logging.Debug("Suche in %v .. %v; m = %v; L[m] = x ==> Element gefunden.", 0, len(L)-1, m)
|
||||
return m
|
||||
} else if len(L) == 1 {
|
||||
logging.Debug("L enthält 1 Element; L[m] =/= x; ==> x nicht in L.")
|
||||
return -1
|
||||
} else if x < L[m] {
|
||||
logging.Debug("Suche in %v .. %v; m = %v; L[m] = %v > x ==> Suche in linker Hälfte fortsetzen.", 0, len(L)-1, m, L[m])
|
||||
index := BinarySearch(L[:m], x)
|
||||
return index
|
||||
} else { // } else if x > L[m] {
|
||||
logging.Debug("Suche in %v .. %v; m = %v; L[m] = %v < x ==> Suche in rechter Hälfte fortsetzen.", 0, len(L)-1, m, L[m])
|
||||
index := BinarySearch(L[m+1:], x)
|
||||
if index == -1 {
|
||||
return -1 // wenn nicht gefunden
|
||||
}
|
||||
return index + (m + 1) // NOTE: muss Indexwert kompensieren
|
||||
}
|
||||
}
|
106
code/golang/pkg/algorithms/search/binary/binary_fancy.go
Normal file
106
code/golang/pkg/algorithms/search/binary/binary_fancy.go
Normal file
@ -0,0 +1,106 @@
|
||||
package binary
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
if !utils.IsSortedListInt(L) {
|
||||
return fmt.Errorf("Ungültiger Input: L muss aufsteigend sortiert sein!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, x int, index int, _ ...interface{}) error {
|
||||
if utils.ArrayContains(L, x) {
|
||||
if !(index >= 0) {
|
||||
return fmt.Errorf("Der Algorithmus sollte nicht -1 zurückgeben.")
|
||||
}
|
||||
if L[index] != x {
|
||||
return fmt.Errorf("Der Algorithmus hat den falschen Index bestimmt.")
|
||||
}
|
||||
} else {
|
||||
if index != -1 {
|
||||
return fmt.Errorf("Der Algorithmus sollte -1 zurückgeben.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM binary search + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyBinarySearch(input_L []int, input_x int) (int, error) {
|
||||
var name = "Binärsuchalgorithmus"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"x": input_x,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_x)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = BinarySearch(input_L, input_x)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_x, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
67
code/golang/pkg/algorithms/search/interpol/interpol.go
Normal file
67
code/golang/pkg/algorithms/search/interpol/interpol.go
Normal file
@ -0,0 +1,67 @@
|
||||
package interpol
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM interpolation
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func InterpolationSearch(L []int, x int, u int, v int) int {
|
||||
if len(L) == 0 {
|
||||
logging.Debug("Liste L leer, also x nicht in L")
|
||||
return -1
|
||||
} else if !(L[u] <= x && x <= L[v]) {
|
||||
logging.Debug("x liegt außerhalb der Grenzen von L")
|
||||
return -1
|
||||
}
|
||||
metrics.AddTimeCost()
|
||||
p := getSuchposition(L, x, u, v)
|
||||
if L[p] == x {
|
||||
logging.Debug("Interpolante in (%[1]v, %[2]v) ist p = %[3]v; L[p] == x; ===> Element gefunden", u, v, p)
|
||||
return p
|
||||
} else if x < L[p] {
|
||||
logging.Debug("Interpolante in (%[1]v, %[2]v) ist p = %[3]v; L[p] > x; ===> suche in linker Hälfte", u, v, p)
|
||||
return InterpolationSearch(L, x, u, p-1)
|
||||
} else { // } else if x > L[p] {
|
||||
logging.Debug("Interpolante in (%[1]v, %[2]v) ist p = %[3]v; L[p] < x; ===> suche in rechter Hälfte", u, v, p)
|
||||
return InterpolationSearch(L, x, p+1, v)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM interpolation
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval.
|
||||
|
||||
Outputs: Interpolierte Position, um Suchinterval ausgeglichen aufzuteilen.
|
||||
*/
|
||||
func getSuchposition(L []int, x int, u int, v int) int {
|
||||
metrics.AddTimeCost()
|
||||
r := float64(x-L[u]) / float64(L[v]-L[u])
|
||||
p := int(math.Floor(float64(u) + r*float64(v-u)))
|
||||
return p
|
||||
}
|
108
code/golang/pkg/algorithms/search/interpol/interpol_fancy.go
Normal file
108
code/golang/pkg/algorithms/search/interpol/interpol_fancy.go
Normal file
@ -0,0 +1,108 @@
|
||||
package interpol
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
if !utils.IsSortedListInt(L) {
|
||||
return fmt.Errorf("Ungültiger Input: L muss aufsteigend sortiert sein!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, x int, index int, _ ...interface{}) error {
|
||||
if utils.ArrayContains(L, x) {
|
||||
if !(index >= 0) {
|
||||
return fmt.Errorf("Der Algorithmus sollte nicht -1 zurückgeben.")
|
||||
}
|
||||
if L[index] != x {
|
||||
return fmt.Errorf("Der Algorithmus hat den falschen Index bestimmt.")
|
||||
}
|
||||
} else {
|
||||
if index != -1 {
|
||||
return fmt.Errorf("Der Algorithmus sollte -1 zurückgeben.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM interpolation + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyInterpolationSearch(input_L []int, input_x int, input_u int, input_v int) (int, error) {
|
||||
var name = "Interpolationssuchalgorithmus"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"x": input_x,
|
||||
"u": input_u,
|
||||
"v": input_v,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_x, input_u, input_v)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = InterpolationSearch(input_L, input_x, input_u, input_v)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_x, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
94
code/golang/pkg/algorithms/search/ith_element/ith_element.go
Normal file
94
code/golang/pkg/algorithms/search/ith_element/ith_element.go
Normal file
@ -0,0 +1,94 @@
|
||||
package ith_element
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find ith smallest
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func FindIthSmallest(L []int, i int) int {
|
||||
n := len(L)
|
||||
// extrahiere Wert + Index des Minimums - bedarf n Schritte
|
||||
metrics.AddTimeCost(n)
|
||||
index := utils.ArgMinInt(L)
|
||||
minValue := L[index]
|
||||
// Falls i = 1, dann wird das Minimum gesucht, sonst Minimum entfernen und nach i-1. Element suchen
|
||||
if i == 1 {
|
||||
logging.Debug("Das i. kleinste Element wurde gefunden.")
|
||||
return minValue
|
||||
} else {
|
||||
logging.Debug("Entferne Minimum: %[1]v.", minValue)
|
||||
i = i - 1
|
||||
L_ := utils.PopIndexListInt(L, index) // entferne Element mit Index = index
|
||||
return FindIthSmallest(L_, i)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find ith smallest (D & C)
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func FindIthSmallestDC(L []int, i int) int {
|
||||
metrics.AddTimeCost()
|
||||
p := L[len(L)-1] // NOTE: Pivotelement kann beliebig gewählt werden
|
||||
// Werte in L in linke und rechte Teillisten um das Pivotelement aufteilen:
|
||||
Ll := []int{} // wird alle Elemente in L < p enthalten
|
||||
Lr := []int{} // wird alle Elemente in L > p enthalten
|
||||
for i := 0; i < len(L); i++ {
|
||||
x := L[i]
|
||||
if x < p {
|
||||
Ll = append(Ll, x)
|
||||
} else if x > p {
|
||||
Lr = append(Lr, x)
|
||||
}
|
||||
}
|
||||
// Fallunterscheidung:
|
||||
if len(Ll) == i-1 {
|
||||
logging.Debug("Es gibt i-1 Elemente vor p=%[1]v. ==> i. kleinste Element = p", p)
|
||||
return p
|
||||
} else if len(Ll) >= i {
|
||||
logging.Debug("Es gibt >= i Elemente vor p=%[1]v. ==> Suche in linker Hälfte!", p)
|
||||
return FindIthSmallestDC(Ll, i)
|
||||
} else {
|
||||
logging.Debug("Es gibt < i-1 Elemente vor p=%[1]v. ==> Suche in rechter Hälfte!", p)
|
||||
i = i - (len(Ll) + 1)
|
||||
return FindIthSmallestDC(Lr, i)
|
||||
}
|
||||
}
|
@ -0,0 +1,163 @@
|
||||
package ith_element
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, i int, _ ...interface{}) error {
|
||||
if !(1 <= i && i <= len(L)) {
|
||||
return fmt.Errorf("Der Wert von i muss zw. %[1]v und %[2]v liegen.", 1, len(L))
|
||||
} else if !utils.ContainsNoDuplicatesListInt(L) {
|
||||
return fmt.Errorf("Ungültiger Input: L darf keine Duplikate enthalten!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, i int, value int, _ ...interface{}) error {
|
||||
L_ := make([]int, len(L))
|
||||
copy(L_, L)
|
||||
sort.Ints(L_)
|
||||
if !(L_[i-1] == value) {
|
||||
return fmt.Errorf("Das i=%[1]v. kleinste Element ist %[2]v und nicht %[3]v.", i, L_[i-1], value)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find ith smallest + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyFindIthSmallest(input_L []int, input_i int) (int, error) {
|
||||
var name = "Auswahlproblem (i. kleinstes Element)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"i": input_i,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_value int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_i)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_value = FindIthSmallest(input_L, input_i)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"value": output_value,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_i, output_value)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_value, err
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find ith smallest (D & C) + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyFindIthSmallestDC(input_L []int, input_i int) (int, error) {
|
||||
var name = "Auswahlproblem (i. kleinstes Element, D & C)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"i": input_i,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_value int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_i)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_value = FindIthSmallestDC(input_L, input_i)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"value": output_value,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_i, output_value)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_value, err
|
||||
}
|
96
code/golang/pkg/algorithms/search/jump/jump.go
Normal file
96
code/golang/pkg/algorithms/search/jump/jump.go
Normal file
@ -0,0 +1,96 @@
|
||||
package jump
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
"ads/pkg/algorithms/search/sequential"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM jump search
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Inputs: L = Liste von Zahlen, x = Zahl, m = lineare Sprunggröße.
|
||||
|
||||
Annahmen:
|
||||
- L sei aufsteigend sortiert.
|
||||
- Idealerweise: L enthält keine Duplikate.
|
||||
- Idealerweise: Abstände zw. Elementen nicht uniform.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
*/
|
||||
func JumpSearchLinear(L []int, x int, m int) int {
|
||||
i0 := 0
|
||||
i1 := m
|
||||
// ACHTUNG: dies ist eine while-Schleife ist golang:
|
||||
for i0 < len(L) {
|
||||
metrics.AddTimeCost()
|
||||
if i1 > len(L) {
|
||||
i1 = len(L)
|
||||
}
|
||||
block := L[i0:i1]
|
||||
elementAfterBlock := block[len(block)-1] + 1
|
||||
if x < elementAfterBlock {
|
||||
logging.Debug("Element muss sich im Block [%[1]v, %[2]v) befinden.", i0, i1)
|
||||
index := sequential.SequentialSearch(block, x)
|
||||
if index == -1 {
|
||||
return -1 // wenn nicht gefunden
|
||||
}
|
||||
return index + i0 // NOTE: muss wegen Offset kompensieren
|
||||
}
|
||||
logging.Debug("Element befindet sich nicht im Block [%[1]v, %[2]v).", i0, i1)
|
||||
i0 = i1
|
||||
i1 += m
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM jump search - exponentiell
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func JumpSearchExponentiell(L []int, x int) int {
|
||||
i0 := 0
|
||||
i1 := 1
|
||||
// ACHTUNG: dies ist eine while-Schleife ist golang:
|
||||
for i0 < len(L) {
|
||||
metrics.AddTimeCost()
|
||||
if i1 > len(L) {
|
||||
i1 = len(L)
|
||||
}
|
||||
block := L[i0:i1]
|
||||
elementAfterBlock := block[len(block)-1] + 1
|
||||
if x < elementAfterBlock {
|
||||
logging.Debug("Element muss sich im Block [%[1]v, %[2]v) befinden.", i0, i1)
|
||||
index := sequential.SequentialSearch(block, x)
|
||||
if index == -1 {
|
||||
return -1 // wenn nicht gefunden
|
||||
}
|
||||
return index + i0 // NOTE: muss wegen Offset kompensieren
|
||||
}
|
||||
logging.Debug("Element befindet sich nicht im Block [%[1]v, %[2]v).", i0, i1)
|
||||
i0 = i1
|
||||
i1 *= 2
|
||||
}
|
||||
return -1
|
||||
}
|
168
code/golang/pkg/algorithms/search/jump/jump_fancy.go
Normal file
168
code/golang/pkg/algorithms/search/jump/jump_fancy.go
Normal file
@ -0,0 +1,168 @@
|
||||
package jump
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
if !utils.IsSortedListInt(L) {
|
||||
return fmt.Errorf("Ungültiger Input: L muss aufsteigend sortiert sein!")
|
||||
}
|
||||
// NOTE: nicht prüfen, ob Duplikate existieren. Das ist nur eine erwünschte aber keine notwendige Annahme.
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, x int, index int, _ ...interface{}) error {
|
||||
if utils.ArrayContains(L, x) {
|
||||
if !(index >= 0) {
|
||||
return fmt.Errorf("Der Algorithmus sollte nicht -1 zurückgeben.")
|
||||
}
|
||||
if L[index] != x {
|
||||
return fmt.Errorf("Der Algorithmus hat den falschen Index bestimmt.")
|
||||
}
|
||||
} else {
|
||||
if index != -1 {
|
||||
return fmt.Errorf("Der Algorithmus sollte -1 zurückgeben.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM jump search + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyJumpSearchLinear(input_L []int, input_x int, input_m int) (int, error) {
|
||||
var name = "Sprungsuche"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"x": input_x,
|
||||
"m": input_m,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_x, input_m)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = JumpSearchLinear(input_L, input_x, input_m)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_x, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM jump search - exponentiell + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyJumpSearchExponentiell(input_L []int, input_x int) (int, error) {
|
||||
var name = "Sprungsuche (exponentiell)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"x": input_x,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_x)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = JumpSearchExponentiell(input_L, input_x)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_x, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
171
code/golang/pkg/algorithms/search/poison/poison.go
Normal file
171
code/golang/pkg/algorithms/search/poison/poison.go
Normal file
@ -0,0 +1,171 @@
|
||||
package poison
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find poison
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func FindPoison(L []int) int {
|
||||
logging.Debug("Bereite Vorkoster vor")
|
||||
n := len(L)
|
||||
testers := [][]int{}
|
||||
for i := 0; i < n; i++ {
|
||||
metrics.AddSpaceCost()
|
||||
logging.Debug("Füge Vorkoster hinzu, der nur Getränk %[1]v testet.", i)
|
||||
testers = append(testers, []int{i})
|
||||
}
|
||||
logging.Debug("Warte auf Effekte")
|
||||
effects := waitForEffects(L, testers)
|
||||
logging.Debug("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
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func FindPoisonFast(L []int) int {
|
||||
logging.Debug("Bereite Vorkoster vor")
|
||||
n := len(L)
|
||||
p := utils.LengthOfBinary(n)
|
||||
testers := [][]int{}
|
||||
// Für jedes Bit i=0 bis p-1 ...
|
||||
for i := 0; i < p; i++ {
|
||||
tester0 := []int{}
|
||||
tester1 := []int{}
|
||||
for k := 0; k < n; k++ {
|
||||
if utils.NthBit(k, i) == 0 {
|
||||
tester0 = append(tester0, k)
|
||||
} else {
|
||||
tester1 = append(tester1, k)
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
metrics.AddSpaceCost(1)
|
||||
logging.Debug("Füge Vorkoster hinzu, der alle Getränke k testet mit %[1]v. Bit von k = 0.", i)
|
||||
testers = append(testers, tester0)
|
||||
testers = append(testers, tester1)
|
||||
}
|
||||
logging.Debug("Warte auf Effekte")
|
||||
effects := waitForEffects(L, testers)
|
||||
logging.Debug("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
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func waitForEffects(L []int, testers [][]int) []int {
|
||||
m := len(testers)
|
||||
effects := make([]int, m)
|
||||
for i, tester := range testers {
|
||||
effect := 0
|
||||
for _, k := range tester {
|
||||
effect += L[k]
|
||||
}
|
||||
effects[i] = effect
|
||||
}
|
||||
return effects
|
||||
}
|
||||
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
func evaluateEffects(testers [][]int, effects []int) []int {
|
||||
var states = map[int]bool{}
|
||||
var poisened = []int{}
|
||||
|
||||
// Werte Effekte aus, um Gift zu lokalisieren:
|
||||
// Zuerst die Indexes der Getränke bei allen vergifteten Tester zusammenführen:
|
||||
for i, tester := range testers {
|
||||
// wenn Tester positiv testet, dann ist eines der von ihm probierten Getränks vergiftet
|
||||
if effects[i] > 0 {
|
||||
// markiere alle vom Tester probierten Getränke
|
||||
for _, k := range tester {
|
||||
states[k] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// jetzt eliminieren wir alle Getränke, die von nicht vergifteten Testern konsumiert wurden:
|
||||
for i, tester := range testers {
|
||||
// wenn Tester negativ testet, dann ist KEINES der von ihm probierten Getränks vergiftet
|
||||
if effects[i] == 0 {
|
||||
// schließe alle vom Tester probierten Getränke aus
|
||||
for _, k := range tester {
|
||||
states[k] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// was übrig bleibt sind die vergifteten Getränke, vorausgesetzt genug Vorkoster wurden ausgewählt
|
||||
for k, state := range states {
|
||||
if state {
|
||||
poisened = append(poisened, k)
|
||||
}
|
||||
}
|
||||
|
||||
return poisened
|
||||
}
|
160
code/golang/pkg/algorithms/search/poison/poison_fancy.go
Normal file
160
code/golang/pkg/algorithms/search/poison/poison_fancy.go
Normal file
@ -0,0 +1,160 @@
|
||||
package poison
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
s := utils.SumListInt(L)
|
||||
if !(s > 0) {
|
||||
return fmt.Errorf("Mindestens ein Getränk muss vergiftet sein!")
|
||||
} else if !(s <= 1) {
|
||||
return fmt.Errorf("Höchstens ein Getränk darf vergiftet sein!")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, index int, _ ...interface{}) error {
|
||||
if !(index >= 0) {
|
||||
return fmt.Errorf("Der Algorithmus hat kein vergiftetes Getränk gefunden, obwohl per Annahme eines existiert.")
|
||||
} else if !(L[index] > 0) {
|
||||
return fmt.Errorf("Der Algorithmus hat das vergiftete Getränk nicht erfolgreich bestimmt.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find poison + Display
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
func FancyFindPoison(input_L []int) (int, error) {
|
||||
var name = "Giftsuche (O(n) Vorkoster)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = FindPoison(input_L)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM find poison fast + Display
|
||||
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
|
||||
|
||||
func FancyFindPoisonFast(input_L []int) (int, error) {
|
||||
var name = "Giftsuche (O(log(n)) Vorkoster)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = FindPoisonFast(input_L)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
37
code/golang/pkg/algorithms/search/sequential/sequential.go
Normal file
37
code/golang/pkg/algorithms/search/sequential/sequential.go
Normal file
@ -0,0 +1,37 @@
|
||||
package sequential
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM sequential search
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Inputs: L = Liste von Zahlen, x = Zahl.
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
*/
|
||||
func SequentialSearch(L []int, x int) int {
|
||||
n := len(L)
|
||||
for i := 0; i < n; i++ {
|
||||
metrics.AddTimeCost()
|
||||
if L[i] == x {
|
||||
logging.Debug("Element in Position %[1]v gefunden.", i)
|
||||
return i
|
||||
}
|
||||
logging.Debug("Element nicht in Position %[1]v.", i)
|
||||
}
|
||||
return -1
|
||||
}
|
104
code/golang/pkg/algorithms/search/sequential/sequential_fancy.go
Normal file
104
code/golang/pkg/algorithms/search/sequential/sequential_fancy.go
Normal file
@ -0,0 +1,104 @@
|
||||
package sequential
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
// Keine Checks!
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, x int, index int, _ ...interface{}) error {
|
||||
if utils.ArrayContains(L, x) {
|
||||
if !(index >= 0) {
|
||||
return fmt.Errorf("Der Algorithmus sollte nicht -1 zurückgeben.")
|
||||
}
|
||||
if L[index] != x {
|
||||
return fmt.Errorf("Der Algorithmus hat den falschen Index bestimmt.")
|
||||
}
|
||||
} else {
|
||||
if index != -1 {
|
||||
return fmt.Errorf("Der Algorithmus sollte -1 zurückgeben.")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD sequential search + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancySequentialSearch(input_L []int, input_x int) (int, error) {
|
||||
var name = "Sequenziellsuchalgorithmus"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
"x": input_x,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_index int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L, input_x)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_index = SequentialSearch(input_L, input_x)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"index": output_index,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, input_x, output_index)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_index, err
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
package next_greater_element
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
"ads/pkg/data_structures/stacks"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM next greater element
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
Inputs: L = Liste von Zahlen.
|
||||
|
||||
Outputs: Liste von Paaren von Elementen und ihrem nächsten größeren Element
|
||||
*/
|
||||
func NextGreaterElement(L []int) [][2]int {
|
||||
output := [][2]int{}
|
||||
|
||||
S := stacks.CREATE()
|
||||
S.INIT()
|
||||
|
||||
for i := 0; i < len(L); i++ {
|
||||
logging.Debug("Stack S | %v", S)
|
||||
logging.Debug("Nächstes List-Element L[%v] = %v betrachten", i, L[i])
|
||||
nextElement := L[i]
|
||||
|
||||
logging.Debug("Alle top Elemente vom Stack, die < nextElement sind, mit L[i] paaren")
|
||||
// Führe aus, bis top Element >= nextElement oder Stack leer ist.
|
||||
for !S.EMPTY() { // ACHTUNG: schreibe 'while' im Pseudocode, denn dies ist eine while-Schleife in golang
|
||||
element := S.TOP()
|
||||
if element < nextElement {
|
||||
// falls top Element < next Element, zum Output hinzufügen und vom Stack entfernen
|
||||
logging.Debug("Stack S | %v; top Element < nextElement; ==> pop und Paar zum Output hinzufügen", S)
|
||||
output = append(output, [2]int{element, nextElement})
|
||||
S.POP()
|
||||
metrics.AddMovesCost()
|
||||
logging.Debug("Stack S | %v", S)
|
||||
} else if element > nextElement {
|
||||
// falls top Element > next Element, auf Stack lassen und Schleife abbrechen.
|
||||
break
|
||||
} else {
|
||||
// falls top Element == next Element, vom Stack entfernen und Schleife abbrechen.
|
||||
S.POP()
|
||||
metrics.AddMovesCost()
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
logging.Debug("L[%v] auf Stack legen", i)
|
||||
S.PUSH(nextElement)
|
||||
metrics.AddMovesCost()
|
||||
}
|
||||
|
||||
logging.Debug("Stack S | %v", S)
|
||||
|
||||
// was übrig bleibt hat kein größeres Element
|
||||
logging.Debug("Alles übrige auf Stack hat kein nächstes größeres Element")
|
||||
for !S.EMPTY() { // ACHTUNG: schreibe 'while' im Pseudocode, denn dies ist eine while-Schleife in golang
|
||||
logging.Debug("Stack S | %v", S)
|
||||
element := S.TOP()
|
||||
output = append(output, [2]int{element, -1})
|
||||
S.POP()
|
||||
metrics.AddMovesCost()
|
||||
}
|
||||
|
||||
logging.Debug("Stack S | %v", S)
|
||||
|
||||
return output
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
package next_greater_element
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, pairs [][2]int, _ ...interface{}) error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM binary search + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyNextGreaterElement(input_L []int) ([][2]int, error) {
|
||||
var name = "Next Greater Element"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
pairs [][2]int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
pairs = NextGreaterElement(input_L)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"pairs": pairs,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, pairs)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pairs, err
|
||||
}
|
167
code/golang/pkg/algorithms/sum/maxsubsum/maxsubsum.go
Normal file
167
code/golang/pkg/algorithms/sum/maxsubsum/maxsubsum.go
Normal file
@ -0,0 +1,167 @@
|
||||
package maxsubsum
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"ads/internal/core/logging"
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/core/utils"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM max sub sum
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
func MaxSubSum(L []int) (int, int, int) {
|
||||
maxSum := 0
|
||||
u := 0
|
||||
v := -1
|
||||
for i := 0; i < len(L); i++ {
|
||||
// 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
|
||||
logging.Debug("max Teilsumme aktualisiert: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum)
|
||||
}
|
||||
}
|
||||
return maxSum, u, v
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM max sub sum (D & C)
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
func MaxSubSumDC(L []int) (int, int, int) {
|
||||
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 = utils.Ceil(float64(len(L)) / 2)
|
||||
Ll := L[:u]
|
||||
Lr := L[u:]
|
||||
// berechnet maximale Teilsumme der linken Hälfte:
|
||||
maxSum1, u1, v1 := MaxSubSumDC(Ll)
|
||||
// berechnet maximale Teilsumme der rechten Hälfte:
|
||||
maxSum2, u2, v2 := MaxSubSumDC(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, Lr)
|
||||
// bestimme Maximum der 3 Möglichkeiten:
|
||||
maxSum = utils.MaxInt(maxSum1, maxSum2, maxSum3)
|
||||
if maxSum == maxSum1 {
|
||||
maxSum, u, v = maxSum1, u1, v1
|
||||
logging.Debug("max Teilsumme kommt in linker Partition vor: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum)
|
||||
} else if maxSum == maxSum3 {
|
||||
maxSum, u, v = maxSum3, u3, v3
|
||||
logging.Debug("max Teilsumme kommt in Überschneidung vor: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum)
|
||||
} else { // } else if maxSum == maxSum2 {
|
||||
maxSum, u, v = maxSum2, u2, v2
|
||||
logging.Debug("max Teilsumme kommt in rechter Partition vor: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum)
|
||||
}
|
||||
}
|
||||
return maxSum, u, v
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* AUXILIARY METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
func lrRandSum(Ll []int, Lr []int) (int, int, int) {
|
||||
maxSumL, u, _ := rRandSum(Ll)
|
||||
maxSumR, _, v := lRandSum(Lr)
|
||||
maxSum := maxSumL + maxSumR
|
||||
v += len(Ll) // offsets kompensieren
|
||||
return maxSum, u, v
|
||||
}
|
||||
|
||||
/*
|
||||
Bestimmt maximale Teilsumme aller nicht leeren linken Segmente einer Liste.
|
||||
|
||||
Inputs: L = Liste von Zahlen
|
||||
|
||||
Outputs: maxSum, u(=0), v
|
||||
*/
|
||||
func lRandSum(L []int) (int, int, int) {
|
||||
n := len(L)
|
||||
// berechne kumulative Summen (vorwärts)
|
||||
metrics.AddTimeCost(n)
|
||||
total := L[0]
|
||||
maxSum := total
|
||||
u := 0
|
||||
v := 0
|
||||
for i := 0; i < n; i++ {
|
||||
total += L[i]
|
||||
if total > maxSum {
|
||||
v = i
|
||||
maxSum = total
|
||||
}
|
||||
}
|
||||
return maxSum, u, v
|
||||
}
|
||||
|
||||
/*
|
||||
Bestimmt maximale Teilsumme aller nicht leeren rechten Segmente einer Liste.
|
||||
|
||||
Inputs: L = Liste von Zahlen
|
||||
|
||||
Outputs: maxSum, u, v(=len(L)-1)
|
||||
*/
|
||||
func rRandSum(L []int) (int, int, int) {
|
||||
n := len(L)
|
||||
// berechne kumulative Summen (rückwärts)
|
||||
metrics.AddTimeCost(n)
|
||||
total := L[n-1]
|
||||
maxSum := total
|
||||
u := n - 1
|
||||
v := n - 1
|
||||
for i := n - 2; i >= 0; i-- {
|
||||
total += L[i]
|
||||
if total > maxSum {
|
||||
u = i
|
||||
maxSum = total
|
||||
}
|
||||
}
|
||||
return maxSum, u, v
|
||||
}
|
160
code/golang/pkg/algorithms/sum/maxsubsum/maxsubsum_fancy.go
Normal file
160
code/golang/pkg/algorithms/sum/maxsubsum/maxsubsum_fancy.go
Normal file
@ -0,0 +1,160 @@
|
||||
package maxsubsum
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"ads/internal/core/metrics"
|
||||
"ads/internal/setup"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* CHECKS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func preChecks(L []int, _ ...interface{}) error {
|
||||
if !(len(L) > 0) {
|
||||
return fmt.Errorf("Liste darf nicht leer sein.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func postChecks(L []int, _ ...interface{}) error {
|
||||
// TODO
|
||||
return nil
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHOD Algorithm + Display
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyMaxSubSum(input_L []int) (int, int, int, error) {
|
||||
var name = "MaxSubSum (Maximale Teilsumme)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_maxSum int
|
||||
output_indexFrom int
|
||||
output_indexTo int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_maxSum, output_indexFrom, output_indexTo = MaxSubSum(input_L)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"maxSum": output_maxSum,
|
||||
"index_from": output_indexFrom,
|
||||
"index_to": output_indexTo,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, output_maxSum, output_indexFrom, output_indexTo)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_maxSum, output_indexFrom, output_indexTo, err
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* ALGORITHM max sub sum (D & C)
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func FancyMaxSubSumDC(input_L []int) (int, int, int, error) {
|
||||
var name = "MaxSubSum (Maximale Teilsumme mit D & C)"
|
||||
var inputs = map[string]interface{}{
|
||||
"L": input_L,
|
||||
}
|
||||
var outputs map[string]interface{}
|
||||
var (
|
||||
output_maxSum int
|
||||
output_indexFrom int
|
||||
output_indexTo int
|
||||
)
|
||||
var err error
|
||||
|
||||
do_once := true
|
||||
for do_once {
|
||||
do_once = false
|
||||
|
||||
// Start Message
|
||||
setup.DisplayStartOfAlgorithm(name, inputs)
|
||||
|
||||
// Prechecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = preChecks(input_L)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Ausführung des Algorithmus:
|
||||
metrics.ResetMetrics()
|
||||
metrics.StartMetrics()
|
||||
output_maxSum, output_indexFrom, output_indexTo = MaxSubSumDC(input_L)
|
||||
metrics.StopMetrics()
|
||||
outputs = map[string]interface{}{
|
||||
"maxSum": output_maxSum,
|
||||
"index_from": output_indexFrom,
|
||||
"index_to": output_indexTo,
|
||||
}
|
||||
|
||||
// Metriken anzeigen
|
||||
if setup.AppConfigShowMetrics() {
|
||||
setup.DisplayMetrics()
|
||||
}
|
||||
|
||||
// End Message
|
||||
setup.DisplayEndOfAlgorithm(outputs)
|
||||
|
||||
// Postchecks:
|
||||
if setup.AppConfigPerformChecks() {
|
||||
err = postChecks(input_L, output_maxSum, output_indexFrom, output_indexTo)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return output_maxSum, output_indexFrom, output_indexTo, err
|
||||
}
|
81
code/golang/pkg/data_structures/queues/queues.go
Normal file
81
code/golang/pkg/data_structures/queues/queues.go
Normal file
@ -0,0 +1,81 @@
|
||||
package queues
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPE
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type QueueInt struct {
|
||||
values *[]int
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS queues
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func CREATE() QueueInt {
|
||||
return QueueInt{}
|
||||
}
|
||||
|
||||
func (S *QueueInt) INIT() {
|
||||
S.values = &[]int{}
|
||||
}
|
||||
|
||||
func (S QueueInt) Length() int {
|
||||
if S.values == nil {
|
||||
return 0
|
||||
}
|
||||
return len(*S.values)
|
||||
}
|
||||
|
||||
func (S QueueInt) String() string {
|
||||
if S.EMPTY() {
|
||||
return "-"
|
||||
}
|
||||
values := []string{}
|
||||
n := S.Length()
|
||||
for i := n - 1; i >= 0; i-- {
|
||||
value := (*S.values)[i]
|
||||
values = append(values, fmt.Sprintf("%v", value))
|
||||
}
|
||||
return fmt.Sprintf(strings.Join(values, " -> "))
|
||||
}
|
||||
|
||||
func (S QueueInt) EMPTY() bool {
|
||||
return S.Length() == 0
|
||||
}
|
||||
|
||||
func (S *QueueInt) ENQUEUE(x int) {
|
||||
if S.values == nil {
|
||||
panic("Queue not initialised!")
|
||||
}
|
||||
*S.values = append(*S.values, x)
|
||||
}
|
||||
|
||||
func (S *QueueInt) FRONT() int {
|
||||
if S.EMPTY() {
|
||||
panic("Cannot read from empty queue!")
|
||||
}
|
||||
return (*S.values)[0]
|
||||
}
|
||||
|
||||
func (S *QueueInt) DEQUEUE() {
|
||||
if S.EMPTY() {
|
||||
panic("Cannot remove from empty queue!")
|
||||
}
|
||||
*S.values = (*S.values)[1:]
|
||||
}
|
81
code/golang/pkg/data_structures/stacks/stacks.go
Normal file
81
code/golang/pkg/data_structures/stacks/stacks.go
Normal file
@ -0,0 +1,81 @@
|
||||
package stacks
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES/CONSTANTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* TYPE
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type StackInt struct {
|
||||
values *[]int
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS stacks
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func CREATE() StackInt {
|
||||
return StackInt{}
|
||||
}
|
||||
|
||||
func (S *StackInt) INIT() {
|
||||
S.values = &[]int{}
|
||||
}
|
||||
|
||||
func (S StackInt) Length() int {
|
||||
if S.values == nil {
|
||||
return 0
|
||||
}
|
||||
return len(*S.values)
|
||||
}
|
||||
|
||||
func (S StackInt) String() string {
|
||||
if S.EMPTY() {
|
||||
return "-"
|
||||
}
|
||||
values := []string{}
|
||||
for _, value := range *S.values {
|
||||
values = append(values, fmt.Sprintf("%v", value))
|
||||
}
|
||||
return fmt.Sprintf(strings.Join(values, ", "))
|
||||
}
|
||||
|
||||
func (S StackInt) EMPTY() bool {
|
||||
return S.Length() == 0
|
||||
}
|
||||
|
||||
func (S *StackInt) PUSH(x int) {
|
||||
if S.values == nil {
|
||||
panic("Stack not initialised!")
|
||||
}
|
||||
*S.values = append(*S.values, x)
|
||||
}
|
||||
|
||||
func (S *StackInt) TOP() int {
|
||||
if S.EMPTY() {
|
||||
panic("Cannot read from empty stack!")
|
||||
}
|
||||
n := S.Length()
|
||||
return (*S.values)[n-1]
|
||||
}
|
||||
|
||||
func (S *StackInt) POP() {
|
||||
if S.EMPTY() {
|
||||
panic("Cannot remove from empty stack!")
|
||||
}
|
||||
n := S.Length()
|
||||
*S.values = (*S.values)[:(n - 1)]
|
||||
}
|
62
code/golang/pkg/re/re.go
Normal file
62
code/golang/pkg/re/re.go
Normal file
@ -0,0 +1,62 @@
|
||||
package re
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* IMPORTS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
)
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* GLOBAL VARIABLES
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
type Reader struct {
|
||||
regex *regexp.Regexp
|
||||
lastpattern *string
|
||||
}
|
||||
|
||||
var defaultReader Reader = Reader{}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* METHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func Matches(pattern string, text string) bool {
|
||||
return defaultReader.Matches(pattern, text)
|
||||
}
|
||||
|
||||
func Sub(pattern string, substitute string, text string) string {
|
||||
return defaultReader.Sub(pattern, substitute, text)
|
||||
}
|
||||
|
||||
func Split(pattern string, text string) []string {
|
||||
return defaultReader.Split(pattern, text)
|
||||
}
|
||||
|
||||
func (r *Reader) Matches(pattern string, text string) bool {
|
||||
r.setReader(pattern)
|
||||
return r.regex.MatchString(text)
|
||||
}
|
||||
|
||||
func (r *Reader) Sub(pattern string, substitute string, text string) string {
|
||||
r.setReader(pattern)
|
||||
return r.regex.ReplaceAllString(text, substitute)
|
||||
}
|
||||
|
||||
func (r *Reader) Split(pattern string, text string) []string {
|
||||
r.setReader(pattern)
|
||||
return r.regex.Split(text, -1)
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------- *
|
||||
* PRIVATE MEHODS
|
||||
* ---------------------------------------------------------------- */
|
||||
|
||||
func (r *Reader) setReader(pattern string) {
|
||||
if r.regex == nil || r.lastpattern == nil || *r.lastpattern != pattern {
|
||||
r.lastpattern = &pattern
|
||||
r.regex = regexp.MustCompile(pattern)
|
||||
}
|
||||
}
|
4
code/golang/requirements
Normal file
4
code/golang/requirements
Normal file
@ -0,0 +1,4 @@
|
||||
github.com/akamensky/argparse@v1.3.1
|
||||
github.com/lithammer/dedent@v1.1.0
|
||||
github.com/stretchr/testify@v1.7.0
|
||||
gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b
|
38
code/python/.gitignore
vendored
Normal file
38
code/python/.gitignore
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
*
|
||||
!/.gitignore
|
||||
|
||||
################################################################
|
||||
# MAIN FOLDER
|
||||
################################################################
|
||||
|
||||
!/Makefile
|
||||
!/README.md
|
||||
!/requirements
|
||||
|
||||
################################################################
|
||||
# PROJECT FILES
|
||||
################################################################
|
||||
|
||||
!/assets
|
||||
!/assets/VERSION
|
||||
!/assets/LOGO
|
||||
!/assets/config.yml
|
||||
|
||||
!/src
|
||||
!/src/**/
|
||||
!/src/**/*.py
|
||||
|
||||
!/test
|
||||
!/test/**/
|
||||
!/test/**/*.py
|
||||
|
||||
## nicht synchronisieren:
|
||||
!/build
|
||||
|
||||
################################################################
|
||||
# ARTEFACTS
|
||||
################################################################
|
||||
|
||||
/**/__pycache__
|
||||
/**/.DS_Store
|
||||
/**/__archive__*
|
27
code/python/Makefile
Normal file
27
code/python/Makefile
Normal file
@ -0,0 +1,27 @@
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# LOCAL ARGUMENTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
PATH_TO_CONFIG:=../config.yml#<- kann durch Pfad zur eigenen yml-Datei ersetzt werden
|
||||
COLOUR:=true
|
||||
PYTHON:=python3
|
||||
PIP:=python3 -m pip
|
||||
|
||||
## für Windows weichen Defaultsettings leicht ab:
|
||||
ifeq ($(OS),Windows_NT)
|
||||
COLOUR:=false# <- man kann als 'true' setzen, aber in Windows funktioniert es möglicherweise nicht
|
||||
PYTHON:=py -3
|
||||
PIP:=py -3 -m pip
|
||||
endif
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# TARGETS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
setup: # TODO: Variant mit venv
|
||||
${PIP} install -r requirements;
|
||||
run: # non-interactive mode mit config-datei
|
||||
${PYTHON} src/main.py run --debug --colour ${COLOUR} --config "${PATH_TO_CONFIG}"
|
||||
run-it: # interactive mode
|
||||
${PYTHON} src/main.py run --it --debug --colour ${COLOUR}
|
||||
# Do everything:
|
||||
all: setup run
|
||||
all-it: setup run-it
|
78
code/python/README.md
Normal file
78
code/python/README.md
Normal file
@ -0,0 +1,78 @@
|
||||
# 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. 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. 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)
|
||||
|
||||
## Einrichten mittels **Makefile** ##
|
||||
|
||||
Führe jeweils
|
||||
|
||||
```bash
|
||||
make setup
|
||||
make run
|
||||
# oder für interaktiven Modus
|
||||
make run-it
|
||||
```
|
||||
|
||||
aus, um Packages zu installieren
|
||||
bzw. den Code auszuführen.
|
||||
Siehe [`Makefile`](./Makefile) für Details zu den Vorgängen.
|
||||
|
||||
Wer Makefile benutzt kann die u. s. Anweisungen ignorieren.
|
||||
|
||||
## 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
3
code/python/assets/LOGO
Normal file
@ -0,0 +1,3 @@
|
||||
+--------------------+
|
||||
| \033[32;1mAlgoDat I\033[0m |
|
||||
+--------------------+
|
1
code/python/assets/VERSION
Normal file
1
code/python/assets/VERSION
Normal file
@ -0,0 +1 @@
|
||||
0.0.0
|
7
code/python/assets/config.yml
Normal file
7
code/python/assets/config.yml
Normal file
@ -0,0 +1,7 @@
|
||||
info:
|
||||
title: "App für ADS1"
|
||||
description: "Interne Configurationsdatei"
|
||||
options:
|
||||
display: true
|
||||
checks: false
|
||||
metrics: true
|
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
42
code/python/src/__main__.py
Normal file
42
code/python/src/__main__.py
Normal file
@ -0,0 +1,42 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# NOTE: This file is needed in addition to main.py
|
||||
# for the creation of an artefact.
|
||||
# It is stored one level higher than src.
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import os;
|
||||
import sys;
|
||||
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.abspath(__file__), '..')));
|
||||
|
||||
from src.setup.cli import *;
|
||||
from src.endpoints.exports import *;
|
||||
from src.main import enter;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXECUTION
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
if __name__ == '__main__':
|
||||
sys.tracebacklimit = 0;
|
||||
try:
|
||||
args = GetArgumentsFromCli(*sys.argv[1:]);
|
||||
except:
|
||||
endpoint_help();
|
||||
exit(1);
|
||||
enter(
|
||||
mode=args.mode,
|
||||
it=args.it,
|
||||
quiet=args.quiet,
|
||||
debug=args.debug,
|
||||
checks=args.checks,
|
||||
colour=args.colour,
|
||||
config=args.config,
|
||||
);
|
0
code/python/src/algorithms/__init__.py
Normal file
0
code/python/src/algorithms/__init__.py
Normal file
10
code/python/src/algorithms/exports.py
Normal file
10
code/python/src/algorithms/exports.py
Normal file
@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.search.exports import *;
|
||||
from src.algorithms.stacks.exports import *;
|
||||
from src.algorithms.sum.exports import *;
|
99
code/python/src/algorithms/methods.py
Normal file
99
code/python/src/algorithms/methods.py
Normal file
@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
import functools
|
||||
|
||||
from src.core.log import *;
|
||||
from src.setup import appconfig;
|
||||
from src.core.metrics 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,
|
||||
outputnames: List[str] = ['result'],
|
||||
preChecks: Any = None,
|
||||
postChecks: Any = None
|
||||
):
|
||||
'''
|
||||
Decorator für Algorithmen, 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);
|
||||
# Prechecks
|
||||
if appconfig.AppConfigPerformChecks() and callable(preChecks):
|
||||
preChecks(**inputs);
|
||||
# Metriken initialisieren + starten
|
||||
ResetMetrics();
|
||||
StartMetrics();
|
||||
# Ausführung des Algorithmus:
|
||||
nonnestedRecursion.trigger();
|
||||
nonnestedAlgorithms.trigger();
|
||||
outputs = func(*[], **inputs);
|
||||
nonnestedAlgorithms.state = state1;
|
||||
nonnestedRecursion.state = state2;
|
||||
if state:
|
||||
# Metriken anhalten
|
||||
StopMetrics();
|
||||
# benenne Outputs:
|
||||
outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]);
|
||||
outputsNamed = { outputnames[k]: value for k, value in enumerate(outputs_) };
|
||||
# Letzte Messages
|
||||
if appconfig.AppConfigShowMetrics():
|
||||
DisplayMetrics();
|
||||
DisplayEndOfAlgorithm(**outputsNamed);
|
||||
# Postchecks
|
||||
if appconfig.AppConfigPerformChecks() 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'], 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;
|
||||
AddTimeCost();
|
||||
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'], 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.
|
||||
'''
|
||||
AddTimeCost();
|
||||
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 find ith smallest element
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@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
|
||||
|
||||
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];
|
||||
AddTimeCost(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 find ith smallest element (D & C)
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@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
|
||||
|
||||
Annahmen:
|
||||
|
||||
- L enthält keine Duplikate.
|
||||
- L enthält mindestens i Elemente.
|
||||
|
||||
Outputs: Wert des i. kleinste Element in L.
|
||||
Beachte 1.kleinstes <==> Minimum.
|
||||
'''
|
||||
AddTimeCost();
|
||||
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);
|
101
code/python/src/algorithms/search/jump.py
Normal file
101
code/python/src/algorithms/search/jump.py
Normal file
@ -0,0 +1,101 @@
|
||||
#!/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!';
|
||||
## NOTE: nicht prüfen, ob Duplikate existieren. Das ist nur eine erwünschte aber keine notwendige Annahme.
|
||||
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'], 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.
|
||||
- Idealerweise: L enthält keine Duplikate.
|
||||
- Idealerweise: Abstände zw. Elementen nicht uniform.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
i = 0;
|
||||
while i*m < len(L):
|
||||
AddTimeCost();
|
||||
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'], preChecks=preChecks, postChecks=postChecks)
|
||||
def JumpSearchExponentiell(L: List[int], x: int) -> int:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen, x = Zahl.
|
||||
|
||||
Annahmen:
|
||||
- L sei aufsteigend sortiert.
|
||||
- Idealerweise: L enthält keine Duplikate.
|
||||
- Idealerweise: Abstände zw. Elementen nicht uniform.
|
||||
|
||||
Outputs: Position von x in L, sonst −1 wenn x nicht in L.
|
||||
'''
|
||||
i0 = 0;
|
||||
i1 = 1;
|
||||
while i0 < len(L):
|
||||
AddTimeCost();
|
||||
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;
|
147
code/python/src/algorithms/search/poison.py
Normal file
147
code/python/src/algorithms/search/poison.py
Normal file
@ -0,0 +1,147 @@
|
||||
#!/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], **_):
|
||||
s = sum(L);
|
||||
assert s > 0, 'Mindestens ein Getränk muss vergiftet sein!';
|
||||
assert s <= 1, 'Höchstens ein Getränk darf vergiftet sein!';
|
||||
return;
|
||||
|
||||
def postChecks(L: List[int], index: int, **_):
|
||||
assert index >= 0, 'Der Algorithmus hat kein vergiftetes Getränk gefunden, obwohl per Annahme eines existiert.';
|
||||
assert L[index] > 0, 'Der Algorithmus hat das vergiftete Getränk nicht erfolgreich bestimmt.';
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM find poison
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@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.
|
||||
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):
|
||||
AddSpaceCost();
|
||||
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'], 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.
|
||||
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.
|
||||
AddSpaceCost(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[int], testers: List[List[int]]) -> List[int]:
|
||||
'''
|
||||
Inputs:
|
||||
- L = Liste von Getränken: durch 0-1 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'], 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):
|
||||
AddTimeCost();
|
||||
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/stacks/__init__.py
Normal file
0
code/python/src/algorithms/stacks/__init__.py
Normal file
8
code/python/src/algorithms/stacks/exports.py
Normal file
8
code/python/src/algorithms/stacks/exports.py
Normal file
@ -0,0 +1,8 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# EXPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.algorithms.stacks.next_greater_element import NextGreaterElement;
|
91
code/python/src/algorithms/stacks/next_greater_element.py
Normal file
91
code/python/src/algorithms/stacks/next_greater_element.py
Normal file
@ -0,0 +1,91 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.local.typing import *;
|
||||
|
||||
from src.core.log import *;
|
||||
from src.core.metrics import *;
|
||||
from src.data_structures.stacks import Stack;
|
||||
from src.algorithms.methods import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CHECKS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def preChecks(L: List[int], **_):
|
||||
# TODO
|
||||
return;
|
||||
|
||||
def postChecks(L: List[int], **_):
|
||||
# TODO
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ALGORITHM next greater element
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
@algorithmInfos(name='NextGreaterElement (with stacks)', outputnames=['pairs'], preChecks=preChecks, postChecks=postChecks)
|
||||
def NextGreaterElement(L: List[int]) -> List[Tuple[int,int]]:
|
||||
'''
|
||||
Inputs: L = Liste von Zahlen.
|
||||
Outputs: Liste von Paaren von Elementen und ihrem nächsten größeren Element
|
||||
'''
|
||||
output = [];
|
||||
|
||||
S = Stack();
|
||||
S.INIT();
|
||||
|
||||
for i in range(len(L)):
|
||||
logDebug('Stack S | {S}'.format(S=S));
|
||||
logDebug('Nächstes List-Element L[{i}] = {el} betrachten'.format(i=i, el=L[i]));
|
||||
nextElement = L[i];
|
||||
|
||||
logDebug('Alle top Elemente vom Stack, die < nextElement sind, mit L[i] paaren');
|
||||
# Führe aus, bis top Element >= nextElement oder Stack leer ist.
|
||||
logDebug('Stack S | {S}'.format(S=S));
|
||||
while not S.EMPTY():
|
||||
element = S.TOP();
|
||||
# falls element < next Element, zum Output hinzufügen und vom Stack entfernen
|
||||
if element < nextElement:
|
||||
logDebug('Stack S | {S}; top Element < nextElement; ==> pop und Paar zum Output hinzufügen'.format(S=S))
|
||||
output.append((element, nextElement));
|
||||
S.POP();
|
||||
AddMovesCost();
|
||||
logDebug('Stack S | {S}'.format(S=S));
|
||||
# falls top Element > next Element, auf Stack lassen und Schleife abbrechen.
|
||||
elif element > nextElement:
|
||||
break
|
||||
# falls top Element == next Element, vom Stack entfernen und Schleife abbrechen.
|
||||
else:
|
||||
S.POP()
|
||||
AddMovesCost()
|
||||
break
|
||||
logDebug('Stack S | {S}'.format(S=S));
|
||||
|
||||
logDebug('L[{i}] auf Stack legen'.format(i=i));
|
||||
S.PUSH(nextElement);
|
||||
AddMovesCost();
|
||||
|
||||
logDebug('Stack S | {S}'.format(S=S));
|
||||
|
||||
# was übrig bleibt hat kein größeres Element
|
||||
logDebug('Alles übrige auf Stack hat kein nächstes größeres Element')
|
||||
while not S.EMPTY():
|
||||
logDebug('Stack S | {S}'.format(S=S));
|
||||
element = S.TOP();
|
||||
S.POP();
|
||||
AddMovesCost();
|
||||
output.append((element, -1));
|
||||
|
||||
logDebug('Stack S | {S}'.format(S=S))
|
||||
return output;
|
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'], 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'], 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)
|
||||
AddTimeCost(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)
|
||||
AddTimeCost(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));
|
121
code/python/src/core/log.py
Normal file
121
code/python/src/core/log.py
Normal file
@ -0,0 +1,121 @@
|
||||
#!/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.utils import StripAnsi;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
_logging_prefix: str = '';
|
||||
_quietmode: bool = False;
|
||||
_debugmode: bool = True;
|
||||
_ansimode: bool = False;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# 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 GetAnsiMode() -> bool:
|
||||
return _ansimode;
|
||||
|
||||
def SetAnsiMode(mode: bool):
|
||||
global _ansimode;
|
||||
_ansimode = mode;
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# 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:
|
||||
line = '{}{}{}'.format('', tag, line);
|
||||
if not _ansimode:
|
||||
line = StripAnsi(line);
|
||||
print(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;
|
145
code/python/src/core/metrics.py
Normal file
145
code/python/src/core/metrics.py
Normal file
@ -0,0 +1,145 @@
|
||||
# !/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from __future__ import annotations;
|
||||
from datetime import datetime;
|
||||
from datetime import timedelta;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
_ctr_time = None;
|
||||
_ctr_space = None;
|
||||
_tmr = None;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASS counter
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class Counter(object):
|
||||
value: int;
|
||||
|
||||
def __init__(self):
|
||||
self.reset();
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self.value);
|
||||
|
||||
def add(self, n: int = 1):
|
||||
self.value += n;
|
||||
return self;
|
||||
|
||||
def reset(self):
|
||||
self.value = 0;
|
||||
return self;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASS timer
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class Timer(object):
|
||||
_time_elapsed: timedelta;
|
||||
_time_current: datetime;
|
||||
_running: bool
|
||||
|
||||
def __init__(self):
|
||||
self.reset();
|
||||
|
||||
def __str__(self) -> str:
|
||||
return str(self._time_elapsed);
|
||||
|
||||
@property
|
||||
def elapsedTime(self) -> timedelta:
|
||||
return self._time_elapsed;
|
||||
|
||||
def start(self):
|
||||
self._time_current = datetime.now();
|
||||
self._running = True
|
||||
return self;
|
||||
|
||||
def stop(self):
|
||||
if self._running:
|
||||
t0 = self._time_current;
|
||||
t1 = datetime.now();
|
||||
delta = t1 - t0;
|
||||
self._time_current = t1;
|
||||
self._time_elapsed += delta;
|
||||
self._running = False
|
||||
return self;
|
||||
|
||||
def reset(self):
|
||||
t = datetime.now();
|
||||
delta = t - t;
|
||||
self._time_current = t;
|
||||
self._time_elapsed = delta;
|
||||
self._running = False
|
||||
return self;
|
||||
|
||||
## Initialisierung:
|
||||
_ctr_time = Counter();
|
||||
_ctr_moves = Counter();
|
||||
_ctr_space = Counter();
|
||||
_tmr = Timer();
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# METHODS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def ResetMetrics():
|
||||
global _ctr_time;
|
||||
global _ctr_moves;
|
||||
global _ctr_space;
|
||||
global _tmr;
|
||||
|
||||
_ctr_time.reset();
|
||||
_ctr_moves.reset();
|
||||
_ctr_space.reset();
|
||||
_tmr.reset();
|
||||
return;
|
||||
|
||||
def StartMetrics():
|
||||
_tmr.start()
|
||||
return;
|
||||
|
||||
def StopMetrics():
|
||||
_tmr.stop()
|
||||
return;
|
||||
|
||||
def AddTimeCost(n: int = 1):
|
||||
global _ctr_time;
|
||||
_ctr_time.add(n);
|
||||
return;
|
||||
|
||||
def AddMovesCost(n: int = 1):
|
||||
global _ctr_moves;
|
||||
_ctr_moves.add(n);
|
||||
return;
|
||||
|
||||
def AddSpaceCost(n: int = 1):
|
||||
global _ctr_space;
|
||||
_ctr_space.add(n);
|
||||
return;
|
||||
|
||||
def SetSpaceCost(n: int):
|
||||
global _ctr_space;
|
||||
_ctr_space.value = n;
|
||||
return;
|
||||
|
||||
def GetTimeCost() -> int:
|
||||
return _ctr_time.value;
|
||||
|
||||
def GetMovesCost() -> int:
|
||||
return _ctr_moves.value;
|
||||
|
||||
def GetSpaceCost() -> int:
|
||||
return _ctr_space.value;
|
||||
|
||||
def GetTimeElapsed() -> timedelta:
|
||||
global _tmr;
|
||||
_tmr.stop();
|
||||
return _tmr.elapsedTime;
|
40
code/python/src/core/utils.py
Normal file
40
code/python/src/core/utils.py
Normal 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;
|
0
code/python/src/data_structures/__init__.py
Normal file
0
code/python/src/data_structures/__init__.py
Normal file
52
code/python/src/data_structures/queues.py
Normal file
52
code/python/src/data_structures/queues.py
Normal file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from local.typing import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASS Queue
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class Queue(object):
|
||||
_initialised: bool;
|
||||
values: List[int];
|
||||
|
||||
def __init__(self):
|
||||
self._initialised = False;
|
||||
|
||||
def INIT(self):
|
||||
self.values = [];
|
||||
self._initialised = True;
|
||||
|
||||
def EMPTY(self) -> bool:
|
||||
return not self._initialised or len(self.values) == 0;
|
||||
|
||||
def ENQUEUE(self, x: int):
|
||||
if not self._initialised:
|
||||
raise Exception('Queue not initialised!')
|
||||
self.values.append(x);
|
||||
|
||||
def FRONT(self) -> int:
|
||||
if self.EMPTY():
|
||||
raise Exception('Cannot read from empty queue!')
|
||||
return self.values[0];
|
||||
|
||||
def DEQUEUE(self) -> int:
|
||||
if self.EMPTY():
|
||||
raise Exception('Cannot remove from empty queue!')
|
||||
self.values = self.values[1:];
|
||||
|
||||
def __str__(self) -> str:
|
||||
if len(self.values) == 0:
|
||||
return '-';
|
||||
return ', '.join([str(x) for x in self.values]);
|
52
code/python/src/data_structures/stacks.py
Normal file
52
code/python/src/data_structures/stacks.py
Normal file
@ -0,0 +1,52 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from local.typing import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# GLOBAL VARIABLES/CONSTANTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
#
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# CLASS Stack
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
class Stack(object):
|
||||
_initialised: bool;
|
||||
values: List[int];
|
||||
|
||||
def __init__(self):
|
||||
self._initialised = False;
|
||||
|
||||
def INIT(self):
|
||||
self.values = [];
|
||||
self._initialised = True;
|
||||
|
||||
def EMPTY(self) -> bool:
|
||||
return not self._initialised or len(self.values) == 0;
|
||||
|
||||
def PUSH(self, x: int):
|
||||
if not self._initialised:
|
||||
raise Exception('Stack not initialised!');
|
||||
self.values.append(x);
|
||||
|
||||
def TOP(self) -> int:
|
||||
if self.EMPTY():
|
||||
raise Exception('Cannot read from empty stack!');
|
||||
return self.values[-1];
|
||||
|
||||
def POP(self) -> int:
|
||||
if self.EMPTY():
|
||||
raise Exception('Cannot remove from empty stack!');
|
||||
self.values = self.values[:-1];
|
||||
|
||||
def __str__(self) -> str:
|
||||
if len(self.values) == 0:
|
||||
return '-';
|
||||
return ', '.join([str(x) for x in self.values]);
|
0
code/python/src/endpoints/__init__.py
Normal file
0
code/python/src/endpoints/__init__.py
Normal file
11
code/python/src/endpoints/exports.py
Normal file
11
code/python/src/endpoints/exports.py
Normal 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;
|
25
code/python/src/endpoints/print.py
Normal file
25
code/python/src/endpoints/print.py
Normal file
@ -0,0 +1,25 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# IMPORTS
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
from src.core.log import *;
|
||||
from src.setup import assets;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT version
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def version():
|
||||
logPlain(assets.Version());
|
||||
return;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT help
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def help():
|
||||
logPlain(assets.Help());
|
||||
return;
|
74
code/python/src/endpoints/run.py
Normal file
74
code/python/src/endpoints/run.py
Normal file
@ -0,0 +1,74 @@
|
||||
#!/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.setup import assets;
|
||||
from src.algorithms.exports import *;
|
||||
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
# ENDPOINT run interactive modus
|
||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
def runInteractive():
|
||||
'''
|
||||
Startet Programm im interaktiven Modus (Konsole).
|
||||
'''
|
||||
logPlain(assets.Logo());
|
||||
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=[]);
|
||||
logPlain(assets.Logo());
|
||||
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-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']);
|
||||
elif command == 'algorithm-stacks-next-greater-element':
|
||||
NextGreaterElement(L=inputs['L']);
|
||||
elif command == 'algorithm-sum-maxsub':
|
||||
MaxSubSum(L=inputs['L']);
|
||||
elif command == 'algorithm-sum-maxsub-dc':
|
||||
MaxSubSumDC(L=inputs['L']);
|
||||
else:
|
||||
raise ValueError('Command \033[1m{}\033[0m nicht erkannt'.format(command));
|
||||
except Exception as e:
|
||||
logError(e);
|
||||
DisplayEndOfCase();
|
||||
return;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user