Compare commits
No commits in common. "master" and "4c13c5ff4751483ca61524d7b4fe1f6b0308b880" have entirely different histories.
master
...
4c13c5ff47
12
.env
12
.env
@ -1,12 +0,0 @@
|
|||||||
# 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,7 +5,6 @@
|
|||||||
# MAIN FOLDER
|
# MAIN FOLDER
|
||||||
################################################################
|
################################################################
|
||||||
|
|
||||||
!/.env
|
|
||||||
!/README.md
|
!/README.md
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
@ -20,16 +19,7 @@
|
|||||||
!/protocol/README.md
|
!/protocol/README.md
|
||||||
!/protocol/woche*.md
|
!/protocol/woche*.md
|
||||||
|
|
||||||
!/scripts
|
|
||||||
!/scripts/*.sh
|
|
||||||
|
|
||||||
!/code
|
!/code
|
||||||
!/code/python
|
|
||||||
!/code/golang
|
|
||||||
!/code/config.yml
|
|
||||||
|
|
||||||
!/dist
|
|
||||||
!/dist/VERSION
|
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# ARTEFACTS
|
# ARTEFACTS
|
||||||
|
30
README.md
30
README.md
@ -1,36 +1,12 @@
|
|||||||
# Algorithmen und Datenstrukturen I, WiSe 2021-22 #
|
# Algorithmen und Datenstrukturen I, WiSe 2021-22 #
|
||||||
|
|
||||||
Diese Repository ist für die Seminargruppe **j/l** am Freitag um 13:15–14:45
|
Diese Repository ist für die Übungsgruppe am Freitag um 13:15–14:45.
|
||||||
im Raum SG 3-14 bzw. SG 4-10 (alternierend).
|
|
||||||
|
|
||||||
**HINWEIS 1:** In diesem Repository werden keine Personen bezogenen Daten der Studierenden gespeichert.
|
**HINWEIS:** In diesem Repository werden keine persönlichen Daten 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:
|
In diesem Repository findet man:
|
||||||
|
|
||||||
- Protokolle der Seminargruppe [hier](./protocol).
|
- Protokolle der Übungsgruppe [hier](./protocol).
|
||||||
- Notizen [hier](./notes).
|
- Notizen [hier](./notes).
|
||||||
- Symbolverzeichnis unter [notes/glossar.md](./notes/glossar.md).
|
- Symbolverzeichnis unter [notes/glossar.md](./notes/glossar.md).
|
||||||
- Referenzen unter [notes/quellen.md](./notes/quellen.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.
|
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
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
33
code/golang/.gitignore
vendored
@ -1,33 +0,0 @@
|
|||||||
*
|
|
||||||
!/.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__*
|
|
@ -1,27 +0,0 @@
|
|||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
# 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
|
|
@ -1,88 +0,0 @@
|
|||||||
# 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.
|
|
@ -1,3 +0,0 @@
|
|||||||
+--------------------+
|
|
||||||
| \033[32;1mAlgoDat I\033[0m |
|
|
||||||
+--------------------+
|
|
@ -1 +0,0 @@
|
|||||||
0.0.0
|
|
@ -1,7 +0,0 @@
|
|||||||
info:
|
|
||||||
title: "App für ADS1"
|
|
||||||
description: "Interne Configurationsdatei"
|
|
||||||
options:
|
|
||||||
display: true
|
|
||||||
checks: false
|
|
||||||
metrics: true
|
|
@ -1,13 +0,0 @@
|
|||||||
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
|
|
||||||
)
|
|
@ -1,21 +0,0 @@
|
|||||||
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=
|
|
@ -1,42 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
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")
|
|
||||||
}
|
|
@ -1,46 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,90 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,147 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
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("")
|
|
||||||
}
|
|
@ -1,173 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,254 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,64 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,146 +0,0 @@
|
|||||||
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,
|
|
||||||
}
|
|
@ -1,76 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,206 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,58 +0,0 @@
|
|||||||
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{}
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
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))
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,60 +0,0 @@
|
|||||||
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")
|
|
||||||
}
|
|
@ -1,130 +0,0 @@
|
|||||||
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 "-"
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
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"`
|
|
||||||
}
|
|
@ -1,109 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,72 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,38 +0,0 @@
|
|||||||
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"`
|
|
||||||
}
|
|
@ -1,103 +0,0 @@
|
|||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,67 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,94 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,163 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,168 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,171 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,89 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,167 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,160 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
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:]
|
|
||||||
}
|
|
@ -1,81 +0,0 @@
|
|||||||
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)]
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,4 +0,0 @@
|
|||||||
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
38
code/python/.gitignore
vendored
@ -1,38 +0,0 @@
|
|||||||
*
|
|
||||||
!/.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__*
|
|
@ -1,27 +0,0 @@
|
|||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
# 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
|
|
@ -1,78 +0,0 @@
|
|||||||
# 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.
|
|
@ -1,3 +0,0 @@
|
|||||||
+--------------------+
|
|
||||||
| \033[32;1mAlgoDat I\033[0m |
|
|
||||||
+--------------------+
|
|
@ -1 +0,0 @@
|
|||||||
0.0.0
|
|
@ -1,7 +0,0 @@
|
|||||||
info:
|
|
||||||
title: "App für ADS1"
|
|
||||||
description: "Interne Configurationsdatei"
|
|
||||||
options:
|
|
||||||
display: true
|
|
||||||
checks: false
|
|
||||||
metrics: true
|
|
@ -1,4 +0,0 @@
|
|||||||
pip>=21.3.1
|
|
||||||
argparse>=1.4.0
|
|
||||||
pyyaml>=5.4.1
|
|
||||||
typing>=3.7.4.3
|
|
@ -1,42 +0,0 @@
|
|||||||
#!/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,
|
|
||||||
);
|
|
@ -1,10 +0,0 @@
|
|||||||
#!/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 *;
|
|
@ -1,99 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,66 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,16 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,72 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,97 +0,0 @@
|
|||||||
#!/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);
|
|
@ -1,101 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,147 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,53 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,8 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
# EXPORTS
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
from src.algorithms.stacks.next_greater_element import NextGreaterElement;
|
|
@ -1,91 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,9 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
# EXPORTS
|
|
||||||
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
from src.algorithms.sum.maxsubsum import MaxSubSum;
|
|
||||||
from src.algorithms.sum.maxsubsum import MaxSubSumDC;
|
|
@ -1,179 +0,0 @@
|
|||||||
#!/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)).
|
|
@ -1,60 +0,0 @@
|
|||||||
#!/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));
|
|
@ -1,121 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,145 +0,0 @@
|
|||||||
# !/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;
|
|
@ -1,40 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,52 +0,0 @@
|
|||||||
#!/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]);
|
|
@ -1,52 +0,0 @@
|
|||||||
#!/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]);
|
|
@ -1,11 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,25 +0,0 @@
|
|||||||
#!/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;
|
|
@ -1,74 +0,0 @@
|
|||||||
#!/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