Compare commits

..

4 Commits

37 changed files with 2448 additions and 112 deletions

View File

@ -3,7 +3,9 @@
Diese Repository ist für die Seminargruppe **j/l** am Freitag um 13:1514:45 Diese Repository ist für die Seminargruppe **j/l** am Freitag um 13:1514:45
im Raum SG 3-14 bzw. SG 4-10 (alternierend). im Raum SG 3-14 bzw. SG 4-10 (alternierend).
**HINWEIS:** In diesem Repository werden keine Personen bezogenen Daten der Studierenden gespeichert. **HINWEIS 1:** In diesem Repository werden keine Personen bezogenen Daten der Studierenden gespeichert.
**HINWEIS 2:** Es besteht absolut gar keine Pflicht, die Materialien in diesem Repo zu verwenden. Diese sind lediglich zusätzliche Hilfsmittel. **Im Zweifelsfalls** sollte man sich immer an den Definitionen und Auslegungen in der VL orientieren.
In diesem Repository findet man: In diesem Repository findet man:
@ -28,8 +30,10 @@ In diesem Repository findet man:
Im Unterordner [`code`](./code) kann man Codeprojekte in Python und Golang finden, in denen verschiedene Algorithmen implementiert werden Im Unterordner [`code`](./code) kann man Codeprojekte in Python und Golang finden, in denen verschiedene Algorithmen implementiert werden
(siehe insbes. [`code/python/src/algorithms`](./code/python//src/algorithms) (siehe insbes. [`code/python/src/algorithms`](./code/python//src/algorithms)
und [`code/golang/pkg/algorithms`](./code/golang/pkg/algorithms)). und [`code/golang/pkg/algorithms`](./code/golang/pkg/algorithms)).
Man kann gerne den Code benutzen, in einer eigenen Repository verändern,
und mit den in dem Kurs präsentierten Algorithmen herumexperimentieren. Gerne kann man den Code benutzen, in einem eigenen Repository verändern, und mit den im Kurs präsentierten Algorithmen **herumexperimentieren**.
**HINWEIS:** _Bei meiner Implementierung kann es zu leichten Abweichungen kommen. Bitte **stets** an dem Material im VL-Skript sich orientieren. Der Hauptzweck der Code-Projekte besteht darin, dass Wissbegierige die Algorithmen konkret ausprobieren können. Alle theoretischen Aspekte werden jedoch im Skript und in den Übungen ausführlicher erklärt._
### Systemvoraussetzungen ### ### Systemvoraussetzungen ###
@ -54,7 +58,7 @@ usw. in der Bash-Console ausführen.
#### Für das Golang-Projekt #### #### Für das Golang-Projekt ####
Man braucht [go](https://golang.org/dl/) Version **1.17.x**. (Man kann bestimmt bei späteren Releases höhere Versionen benutzen. Man muss lediglich dann in [`./code/golang/go.mod`](./code/golang/go.mod) die Version hochstellen und die Requirements nochmals installieren lassen.) Und einige Packages werden benötigen. Letztere lassen sich mittels Man braucht [go](https://golang.org/dl/) Version **1.17.x**. (Man kann bestimmt bei späteren Releases höhere Versionen benutzen. Man muss lediglich dann in [`./code/golang/go.mod`](./code/golang/go.mod) die Version hochstellen und die Requirements nochmals installieren lassen.) Und einige Packages werden benötigt. Letztere lassen sich mittels
```bash ```bash
./scripts/build.sh --lang go --mode setup ./scripts/build.sh --lang go --mode setup
``` ```
@ -64,10 +68,9 @@ installieren.
Python version 3.x.x (idealerweise zumindest 3.9.5) plus einige Module (siehe [code/requirements](./code/requirements)). Letztere lassen sich mittels Python version 3.x.x (idealerweise zumindest 3.9.5) plus einige Module (siehe [code/requirements](./code/requirements)). Letztere lassen sich mittels
```bash ```bash
# Benutze die Option `--venv true`, um mit virtuellem Env zu arbeiten:
./scripts/build.sh --lang python --mode setup ./scripts/build.sh --lang python --mode setup
## mit virtuellem Env: ## oder:
./scripts/build.sh --lang python --venv true --mode setup
## alternative:
python3 -m pip install -r code/requirements; # linux, osx python3 -m pip install -r code/requirements; # linux, osx
py -3 -m pip install -r code/requirements; # Windows py -3 -m pip install -r code/requirements; # Windows
``` ```
@ -105,7 +108,7 @@ py -3 main.py run [--debug]; # Windows
popd; ## <- zum vorherigen Pfad zurückwechseln popd; ## <- zum vorherigen Pfad zurückwechseln
``` ```
Oder man erstelle einen bash Skript wie `run.sh`, trage die Befehle da ein und führe Oder man erstelle ein bash Skript wie `run.sh`, trage die Befehle da ein und führe
```bash ```bash
chmod +x run.sh; # nur einmalig nötig chmod +x run.sh; # nur einmalig nötig
./run.sh ./run.sh

View File

@ -36,7 +36,7 @@ parts:
- command: 'algorithm-search-poison' - command: 'algorithm-search-poison'
description: 'Freiwilliges ÜB2, A4, Beispiel' description: 'Freiwilliges ÜB2, A4, Beispiel'
inputs: &ref_inputs_ueb2_4 inputs: &ref_inputs_ueb2_4
L: [ false, false, false, false, false, false, false, false, true, false, false, false, false, false ] L: [ 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 ]
- command: 'algorithm-search-poison-fast' - command: 'algorithm-search-poison-fast'
description: 'Freiwilliges ÜB2, A4, Beispiel' description: 'Freiwilliges ÜB2, A4, Beispiel'
inputs: *ref_inputs_ueb2_4 inputs: *ref_inputs_ueb2_4

View File

@ -0,0 +1,53 @@
package binary
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"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.LogDebug(fmt.Sprintf("x nicht in L"))
return -1
}
metrics.AddTimeCost()
m := int(len(L) / 2)
if L[m] == x {
logging.LogDebug(fmt.Sprintf("x in Position m gefunden"))
return m
} else if x < L[m] {
logging.LogDebug(fmt.Sprintf("Suche in linker Hälfte fortsetzen."))
index := BinarySearch(L[:m], x)
return index
} else { // } else if x > L[m] {
logging.LogDebug(fmt.Sprintf("Suche in rechter Hälfte fortsetzen."))
index := BinarySearch(L[m+1:], x)
if index >= 0 {
index += (m + 1) // NOTE: muss Indexwert kompensieren
}
return index
}
}

View File

@ -0,0 +1,94 @@
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_x)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = BinarySearch(input_L, input_x)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, input_x, output_index)
if err != nil {
break
}
}
return output_index, err
}

View File

@ -0,0 +1,69 @@
package interpol
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"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.LogDebug(fmt.Sprintf("Liste L leer, also x nicht in L"))
return -1
} else if !(L[u] <= x && x <= L[v]) {
logging.LogDebug(fmt.Sprintf("x liegt außerhalb der Grenzen von L"))
return -1
}
metrics.AddTimeCost()
p := getSuchposition(L, x, u, v)
logging.LogDebug(fmt.Sprintf("Interpolante von x in (u, v)=(%[1]v, %[2]v) ist p = %[3]v.", u, v, p))
if L[p] == x {
logging.LogDebug(fmt.Sprintf("x in Position p gefunden"))
return p
} else if x < L[p] {
logging.LogDebug(fmt.Sprintf("Suche in linker Hälfte fortsetzen."))
return InterpolationSearch(L, x, u, p-1)
} else { // } else if x > L[p] {
logging.LogDebug(fmt.Sprintf("Suche in rechter Hälfte fortsetzen."))
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
}

View File

@ -0,0 +1,96 @@
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_x, input_u, input_v)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = InterpolationSearch(input_L, input_x, input_u, input_v)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, input_x, output_index)
if err != nil {
break
}
}
return output_index, err
}

View File

@ -0,0 +1,96 @@
package ith_element
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"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.LogDebug("Das i. kleinste Element wurde gefunden.")
return minValue
} else {
logging.LogDebug(fmt.Sprintf("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.LogDebug(fmt.Sprintf("Es gibt i-1 Elemente vor p=%[1]v. ==> i. kleinste Element = p", p))
return p
} else if len(Ll) >= i {
logging.LogDebug(fmt.Sprintf("Es gibt >= i Elemente vor p=%[1]v. ==> Suche in linker Hälfte!", p))
return FindIthSmallestDC(Ll, i)
} else {
logging.LogDebug(fmt.Sprintf("Es gibt < i-1 Elemente vor p=%[1]v. ==> Suche in rechter Hälfte!", p))
i = i - (len(Ll) + 1)
return FindIthSmallestDC(Lr, i)
}
}

View File

@ -0,0 +1,139 @@
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_i)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_value = FindIthSmallest(input_L, input_i)
outputs = map[string]interface{}{
"value": output_value,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_i)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_value = FindIthSmallestDC(input_L, input_i)
outputs = map[string]interface{}{
"value": output_value,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, input_i, output_value)
if err != nil {
break
}
}
return output_value, err
}

View File

@ -0,0 +1,91 @@
package jump
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"ads/internal/algorithms/search/sequential"
"ads/internal/core/logging"
"ads/internal/core/metrics"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES/CONSTANTS
* ---------------------------------------------------------------- */
//
/* ---------------------------------------------------------------- *
* ALGORITHM jump search
* ---------------------------------------------------------------- */
/*
Inputs: L = Liste von Zahlen, x = Zahl, m = lineare Sprunggröße.
Annahmen:
- L sei aufsteigend sortiert.
- L enthält keine Duplikate.
Outputs: Position von x in L, sonst 1 wenn x nicht in L.
*/
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()
block := L[i0:i1]
elementAfterBlock := block[len(block)-1] + 1
if x < elementAfterBlock {
logging.LogDebug(fmt.Sprintf("Element muss sich im Block [%[1]v, %[2]v) befinden.", i0, i1))
index := sequential.SequentialSearch(block, x)
if index >= 0 {
index += i0 // NOTE: muss wegen Offset kompensieren
}
return index
}
logging.LogDebug(fmt.Sprintf("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()
block := L[i0:i1]
elementAfterBlock := block[len(block)-1] + 1
if x < elementAfterBlock {
logging.LogDebug(fmt.Sprintf("Element muss sich im Block [%[1]v, %[2]v) befinden.", i0, i1))
index := sequential.SequentialSearch(block, x)
if index >= 0 {
index += i0 // NOTE: muss wegen Offset kompensieren
}
return index
}
logging.LogDebug(fmt.Sprintf("Element befindet sich nicht im Block [%[1]v, %[2]v).", i0, i1))
i0 = i1
i1 *= 2
}
return -1
}

View File

@ -0,0 +1,143 @@
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!")
}
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_x, input_m)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = JumpSearchLinear(input_L, input_x, input_m)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_x)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = JumpSearchExponentiell(input_L, input_x)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, input_x, output_index)
if err != nil {
break
}
}
return output_index, err
}

View File

@ -0,0 +1,173 @@
package poison
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"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.LogDebug("Bereite Vorkoster vor")
n := len(L)
testers := [][]int{}
for i := 0; i < n; i++ {
metrics.AddSpaceCost()
logging.LogDebug(fmt.Sprintf("Füge Vorkoster hinzu, der nur Getränk %[1]v testet.", i))
testers = append(testers, []int{i})
}
logging.LogDebug("Warte auf Effekte")
effects := waitForEffects(L, testers)
logging.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
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
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.LogDebug("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.LogDebug(fmt.Sprintf("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.LogDebug("Warte auf Effekte")
effects := waitForEffects(L, testers)
logging.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
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*
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
}

View File

@ -0,0 +1,136 @@
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = FindPoison(input_L)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = FindPoisonFast(input_L)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, output_index)
if err != nil {
break
}
}
return output_index, err
}

View File

@ -0,0 +1,39 @@
package sequential
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"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.LogDebug(fmt.Sprintf("Element in Position %[1]v gefunden.", i))
return i
}
logging.LogDebug(fmt.Sprintf("Element nicht in Position %[1]v.", i))
}
return -1
}

View File

@ -0,0 +1,92 @@
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L, input_x)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_index = SequentialSearch(input_L, input_x)
outputs = map[string]interface{}{
"index": output_index,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, input_x, output_index)
if err != nil {
break
}
}
return output_index, err
}

View File

@ -0,0 +1,169 @@
package maxsubsum
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"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.LogDebug(fmt.Sprintf("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.LogDebug(fmt.Sprintf("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.LogDebug(fmt.Sprintf("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.LogDebug(fmt.Sprintf("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
}

View File

@ -0,0 +1,136 @@
package maxsubsum
import (
"fmt"
"ads/internal/core/metrics"
"ads/internal/setup"
)
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
/* ---------------------------------------------------------------- *
* 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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_maxSum, output_indexFrom, output_indexTo = MaxSubSum(input_L)
outputs = map[string]interface{}{
"maxSum": output_maxSum,
"index_from": output_indexFrom,
"index_to": output_indexTo,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
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
setup.DisplayStartOfAlgorithm(name, inputs)
metrics.RestartMetrics()
// Prechecks:
err = preChecks(input_L)
if err != nil {
break
}
// Ausführung des Algorithmus:
output_maxSum, output_indexFrom, output_indexTo = MaxSubSumDC(input_L)
outputs = map[string]interface{}{
"maxSum": output_maxSum,
"index_from": output_indexFrom,
"index_to": output_indexTo,
}
// Letzte Messages:
setup.DisplayMetrics()
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
err = postChecks(input_L, output_maxSum, output_indexFrom, output_indexTo)
if err != nil {
break
}
}
return output_maxSum, output_indexFrom, output_indexTo, err
}

View File

@ -0,0 +1,50 @@
package metrics
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"time"
"ads/internal/types"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES/CONSTANTS
* ---------------------------------------------------------------- */
var _ctr_time = types.NewCounter()
var _ctr_space = types.NewCounter()
var _tmr = types.NewTimer()
/* ---------------------------------------------------------------- *
* METHODS
* ---------------------------------------------------------------- */
func RestartMetrics() {
_tmr.Reset()
_ctr_time.Reset()
_ctr_space.Reset()
}
func AddTimeCost(options ...int) {
_ctr_time.Add(options...)
}
func AddSpaceCost(options ...int) {
_ctr_space.Add(options...)
}
func GetTimeCost() int {
return _ctr_time.Size()
}
func GetSpaceCost() int {
return _ctr_space.Size()
}
func GetTimeElapsed() time.Duration {
_tmr.Stop()
return _tmr.ElapsedTime()
}

View File

@ -24,26 +24,41 @@ func ArrayContains(x interface{}, elem interface{}) bool {
return false return false
} }
// func ListComprehension(x interface{}, cond (interface{}) bool) 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 array contains * METHOD sort
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */
func UniqueListOfStrings(X []string) []string { 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 var ok bool
m := map[string]bool{} m := map[int]bool{}
X_unique := []string{} X_unique := []int{}
for _, x := range X { for _, x := range X {
if _, ok = m[x]; !ok { if _, ok = m[x]; !ok {
X_unique = append(X_unique, x) X_unique = append(X_unique, x)
@ -52,6 +67,10 @@ func UniqueListOfStrings(X []string) []string {
return X_unique return X_unique
} }
func ContainsNoDuplicatesListInt(X []int) bool {
return len(X) <= len(UniqueListInt(X))
}
/* ---------------------------------------------------------------- * /* ---------------------------------------------------------------- *
* METHOD get value from array of unknown length * METHOD get value from array of unknown length
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */

View File

@ -0,0 +1,147 @@
package utils
/*
In Golang sind manche (basic!) mathematischen Vorgänge etwas umständlich zu implementieren.
Wir wollen diese Methoden komplett einhüllen, damit wir von ihrer Komplexität
in den Algorithmen nicht abgelenkt werden.
*/
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"math"
"strconv"
)
/* ---------------------------------------------------------------- *
* METHOD floor, ceil
* ---------------------------------------------------------------- */
func Floor(x float64) int {
return int(math.Floor(x))
}
func Ceil(x float64) int {
return int(math.Ceil(x))
}
/* ---------------------------------------------------------------- *
* METHOD max, min
* ---------------------------------------------------------------- */
func MinInt(x int, y ...int) int {
if len(y) == 0 {
return x
} else if x < y[0] {
return MinInt(x, y[1:]...)
} else {
return MinInt(y[0], y[1:]...)
}
}
func MaxInt(x int, y ...int) int {
if len(y) == 0 {
return x
} else if x > y[0] {
return MaxInt(x, y[1:]...)
} else {
return MaxInt(y[0], y[1:]...)
}
}
func ArgMinInt(X []int) int {
if len(X) == 0 {
return -1
}
minValue := X[0]
index := 0
for i, x := range X {
if x < minValue {
minValue = x
index = i
}
}
return index
}
func ArgMaxInt(X []int) int {
if len(X) == 0 {
return -1
}
maxValue := X[0]
index := 0
for i, x := range X {
if x > maxValue {
maxValue = x
index = i
}
}
return index
}
/* ---------------------------------------------------------------- *
* METHOD sum
* ---------------------------------------------------------------- */
func SumListInt(X []int) int {
result := 0
for _, x := range X {
result += x
}
return result
}
func SumListFloat(X []float64) float64 {
result := 0.
for _, x := range X {
result += x
}
return result
}
/* ---------------------------------------------------------------- *
* METHODS binary
* ---------------------------------------------------------------- */
/*
Für eine Zahl n != 0 liefert die Länge der binären Darstellung der Zahl,
und für n == 0 liefert 0
*/
func LengthOfBinary(number int) int {
if number == 0 {
return 0
}
if number < 0 {
number = -number
}
number_binary := fmt.Sprintf("%b", int64(number))
return len([]rune(number_binary))
}
/*
Für eine Zahl n != 0 liefert die Bits der binären Darstellung
*/
func IntToBinary(number int) []int {
if number == 0 || number == 1 {
return []int{number}
}
number_binary := fmt.Sprintf("%b", int64(number))
runes := []rune(number_binary)
bits := make([]int, len(runes))
for i, rune := range runes {
bit, _ := strconv.ParseInt(fmt.Sprintf("%c", rune), 2, 64)
bits[len(runes)-1-i] = int(bit)
}
return bits
}
func NthBit(number int, digit int) int {
bits := IntToBinary(number)
if digit < len(bits) {
return bits[digit]
}
return 0
}

View File

@ -5,16 +5,148 @@ package endpoints
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */
import ( import (
"ads/internal/core/logging"
"ads/internal/setup" "ads/internal/setup"
"ads/internal/types"
"fmt"
algorithm_search_binary "ads/internal/algorithms/search/binary"
algorithm_search_interpol "ads/internal/algorithms/search/interpol"
algorithm_search_ith_element "ads/internal/algorithms/search/ith_element"
algorithm_search_jump "ads/internal/algorithms/search/jump"
algorithm_search_poison "ads/internal/algorithms/search/poison"
algorithm_search_sequential "ads/internal/algorithms/search/sequential"
algorithm_sum_maxsubsum "ads/internal/algorithms/sum/maxsubsum"
"ads/internal/core/logging"
) )
/* ---------------------------------------------------------------- * /* ---------------------------------------------------------------- *
* ENDPOINT run * ENDPOINT run
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */
func Run(fnameConfig string) error { // Liest Config Datei ein und führt Algorithmen auf Fälle durch
func Run(path string) error {
var err error
var err_case error
logging.LogPlain(setup.Logo()) logging.LogPlain(setup.Logo())
logging.LogWarn("Die Go-Implementierung ist noch unter Arbeit.")
// extrahiere user config
config := setup.NewUserConfig()
err = setup.GetUserConfig(path, &config)
if err != nil {
return err
}
// Fälle extrahieren
cases := []types.CaseConfig{}
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.InputsConfig{}
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-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.LogError(err_case)
}
}
setup.DisplayEndOfCase()
return nil return nil
} }

View File

@ -0,0 +1,116 @@
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.LogPlain(fmt.Sprintf("\033[92;1mCASE %[1]v\033[0m.", index))
} else {
logging.LogPlain(fmt.Sprintf("\033[92;1mCASE %[1]v\033[0m (\033[1;2m%[2]s\033[0m).", index, *descr))
}
}
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.LogPlain(fmt.Sprintf("Ausführung vom Algorithmus: \033[92;1m%[1]s\033[0m", name))
logging.LogPlain("INPUTS")
for varname, value := range inputs {
logging.LogPlain(fmt.Sprintf(" - %[1]s = %[2]v", varname, RepresentValue(value)))
}
}
func DisplayEndOfAlgorithm(outputs map[string]interface{}) {
logging.LogPlain("OUTPUTS:")
for varname, value := range outputs {
logging.LogPlain(fmt.Sprintf(" - %[1]s = %[2]v", varname, RepresentValue(value)))
}
}
func DisplayMetrics() {
logging.LogPlain(fmt.Sprintf("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsed()))
logging.LogPlain(fmt.Sprintf("Kosten (Zeit): T(n) = \033[1m%[1]v\033[0m", metrics.GetTimeCost()))
logging.LogPlain(fmt.Sprintf("Kosten (Platz): S(n) = \033[1m%[1]v\033[0m", metrics.GetSpaceCost()))
return
}
/* ---------------------------------------------------------------- *
* METHODS Verschiedenes
* ---------------------------------------------------------------- */
func DisplayBar(options ...int) {
n := 80
if len(options) > 0 {
n = options[0]
}
logging.LogPlain(fmt.Sprintf("+%[1]s+", strings.Repeat("-", n)))
return
}

View File

@ -0,0 +1,30 @@
package setup
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"ads/internal/types"
"io/ioutil"
"gopkg.in/yaml.v3"
)
/* ---------------------------------------------------------------- *
* 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
}

View File

@ -0,0 +1,109 @@
package types
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"reflect"
)
/* ---------------------------------------------------------------- *
* METHOD convert basic types to pointers
* ---------------------------------------------------------------- */
/****
* NOTE: these cannot be replaced by inline variants, e.g.
* var x string
* var xx *string = &x
* as then the values are tied.
* These methods create addresses to clones of the original variables,
* and do not coincide with the addresses of the original variables.
****/
func StructToPtr(x struct{}) *struct{} {
var value = x
return &value
}
func InterfaceToPtr(x interface{}) *interface{} {
var value = x
return &value
}
func BoolToPtr(x bool) *bool {
var value = x
return &value
}
func StringToPtr(x string) *string {
var value = x
return &value
}
func IntToPtr(x int) *int {
var value = x
return &value
}
/* ---------------------------------------------------------------- *
* METHOD get value from ptr with default
* ---------------------------------------------------------------- */
func ExpandPtrToBool(p *bool) interface{} {
if p != nil {
return *p
}
return p
}
func PtrToBool(p *bool, Default bool) bool {
if p != nil {
return *p
}
return Default
}
func ExpandPtrToString(p *string) interface{} {
if p != nil {
return *p
}
return p
}
func PtrToString(p *string, Default string) string {
if p != nil {
return *p
}
return Default
}
func ExpandPtrToInt(p *int) interface{} {
if p != nil {
return *p
}
return p
}
func PtrToInt(p *int, Default int) int {
if p != nil {
return *p
}
return Default
}
/* ---------------------------------------------------------------- *
* METHOD interface to (ptr to) array
* ---------------------------------------------------------------- */
func InterfaceToArray(x interface{}) *[]interface{} {
if reflect.TypeOf(x).Kind() == reflect.Slice {
var xSlice []interface{} = []interface{}{}
var xConverted = reflect.ValueOf(x)
for i := 0; i < xConverted.Len(); i++ {
xSlice = append(xSlice, xConverted.Index(i).Interface())
}
return &xSlice
}
return nil
}

View File

@ -0,0 +1,52 @@
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) Add(options ...int) {
n := 1
if len(options) > 0 {
n = options[0]
}
self.nr += n
}
func (self *Counter) Reset() {
self.nr = 0
}

View File

@ -0,0 +1,66 @@
package types
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"time"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES/CONSTANTS
* ---------------------------------------------------------------- */
//
/* ---------------------------------------------------------------- *
* TYPE Timer
* ---------------------------------------------------------------- */
type Timer struct {
time_elapsed time.Duration
time_current time.Time
}
/* ---------------------------------------------------------------- *
* 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()
}
func (self *Timer) Stop() {
t0 := self.time_current
t1 := time.Now()
delta := t1.Sub(t0)
self.time_current = t1
self.time_elapsed += delta
}
func (self *Timer) Reset() {
t := time.Now()
delta := t.Sub(t) // d. h. 0
self.time_current = t
self.time_elapsed = delta
}

View File

@ -0,0 +1,38 @@
package types
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
//
/* ---------------------------------------------------------------- *
* YAML SCHEMES
* ---------------------------------------------------------------- */
type UserConfig struct {
Info *InfoConfig `yaml:"info"`
Parts *PartsConfig `yaml:"parts"`
}
type InfoConfig struct {
Title *string `yaml:"title"`
Description *string `yaml:"description"`
}
type PartsConfig struct {
Cases *([]CaseConfig) `yaml:"cases"`
}
type CaseConfig struct {
Command *string `yaml:"command"`
Description *string `yaml:"description"`
Inputs *InputsConfig `yaml:"inputs"`
}
type InputsConfig struct {
List *[]int `yaml:"L"`
SearchRank *int `yaml:"i"`
SearchValue *int `yaml:"x"`
JumpSize *int `yaml:"m"`
}

View File

@ -8,6 +8,7 @@
import functools; import functools;
from src.core.log import *; from src.core.log import *;
from src.core.metrics import *;
from src.setup.display import *; from src.setup.display import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -39,12 +40,12 @@ def algorithmInfos(
name: str, name: str,
checks: bool = True, checks: bool = True,
metrics: bool = None, metrics: bool = None,
outputnames: Union[str, Tuple[str]] = 'result', outputnames: List[str] = ['result'],
preChecks: Any = None, preChecks: Any = None,
postChecks: Any = None postChecks: Any = None
): ):
''' '''
Decorator für Algorthmen, der Folgendes macht: Decorator für Algorithmen, der Folgendes macht:
- Zeigt vorm Start Console-Messages mit Namen des Algorithmus + Inputs. - Zeigt vorm Start Console-Messages mit Namen des Algorithmus + Inputs.
- Zeit am Ende optional Metriken (bspw. Zeitkosten). - Zeit am Ende optional Metriken (bspw. Zeitkosten).
@ -65,7 +66,7 @@ def algorithmInfos(
if state: if state:
# Initialisierung # Initialisierung
DisplayStartOfAlgorithm(name, **inputs); DisplayStartOfAlgorithm(name, **inputs);
RestartCounter(); RestartMetrics();
# Prechecks # Prechecks
if checks and callable(preChecks): if checks and callable(preChecks):
preChecks(**inputs); preChecks(**inputs);
@ -78,8 +79,7 @@ def algorithmInfos(
if state: if state:
# benenne Outputs: # benenne Outputs:
outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]); outputs_ = outputs if isinstance(outputs, tuple) else tuple([outputs]);
outputnames_ = outputnames if isinstance(outputnames, tuple) else tuple([outputnames]); outputsNamed = { outputnames[k]: value for k, value in enumerate(outputs_) };
outputsNamed = { outputnames_[k]: value for k, value in enumerate(outputs_) };
# Letzte Messages # Letzte Messages
if metrics: if metrics:
DisplayMetrics(); DisplayMetrics();

View File

@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM binary search # ALGORITHM binary search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Binärsuchalgorithmus', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Binärsuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def BinarySearch(L: List[int], x: int) -> int: def BinarySearch(L: List[int], x: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, x = Zahl. Inputs: L = Liste von Zahlen, x = Zahl.
@ -49,7 +49,7 @@ def BinarySearch(L: List[int], x: int) -> int:
if len(L) == 0: if len(L) == 0:
logDebug('x nicht in L'); logDebug('x nicht in L');
return -1; return -1;
AddToCounter(); AddTimeCost();
m = math.floor(len(L)/2); m = math.floor(len(L)/2);
if L[m] == x: if L[m] == x:
logDebug('x in Position m gefunden'); logDebug('x in Position m gefunden');

View File

@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM interpolation # ALGORITHM interpolation
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Interpolationssuchalgorithmus', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Interpolationssuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def InterpolationSearch(L: List[int], x: int, u: int, v: int) -> int: def InterpolationSearch(L: List[int], x: int, u: int, v: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval. Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval.
@ -66,7 +66,7 @@ def getSuchposition(L: List[int], x: int, u: int, v: int) -> int:
Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval. Inputs: L = Liste von Zahlen, x = Zahl, [u, v] = Suchinterval.
Outputs: Interpolierte Position, um Suchinterval ausgeglichen aufzuteilen. Outputs: Interpolierte Position, um Suchinterval ausgeglichen aufzuteilen.
''' '''
AddToCounter(); AddTimeCost();
r = (x - L[u])/(L[v]-L[u]); r = (x - L[u])/(L[v]-L[u]);
p = math.floor(u + r*(v-u)) p = math.floor(u + r*(v-u))
return p; return p;

View File

@ -33,10 +33,10 @@ def postChecks(L: List[int], i: int, value: int, **_):
return; return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM jump search # ALGORITHM find ith smallest element
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames='value', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Auswahlproblem (i. kleinstes Element)', outputnames=['value'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def FindIthSmallest(L: List[int], i: int) -> int: def FindIthSmallest(L: List[int], i: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, i = Ordinalzahl Inputs: L = Liste von Zahlen, i = Ordinalzahl
@ -51,7 +51,7 @@ def FindIthSmallest(L: List[int], i: int) -> int:
''' '''
index = 0; index = 0;
minValue = L[0]; minValue = L[0];
AddToCounter(len(L)); AddTimeCost(len(L));
for i_ in range(1, len(L)): for i_ in range(1, len(L)):
if L[i_] < minValue: if L[i_] < minValue:
index = i_; index = i_;
@ -65,10 +65,10 @@ def FindIthSmallest(L: List[int], i: int) -> int:
return FindIthSmallest(L=L[:index] + L[(index+1):], i=i); return FindIthSmallest(L=L[:index] + L[(index+1):], i=i);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM jump search (D & C) # ALGORITHM find ith smallest element (D & C)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames='value', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Auswahlproblem (i. kleinstes Element, D & C)', outputnames=['value'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def FindIthSmallestDC(L: List[int], i: int) -> int: def FindIthSmallestDC(L: List[int], i: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, i = Ordinalzahl Inputs: L = Liste von Zahlen, i = Ordinalzahl
@ -81,7 +81,7 @@ def FindIthSmallestDC(L: List[int], i: int) -> int:
Outputs: Wert des i. kleinste Element in L. Outputs: Wert des i. kleinste Element in L.
Beachte 1.kleinstes <==> Minimum. Beachte 1.kleinstes <==> Minimum.
''' '''
AddToCounter(); AddTimeCost();
p = L[len(L)-1]; # NOTE: Pivotelement kann beliebig gewählt werden p = L[len(L)-1]; # NOTE: Pivotelement kann beliebig gewählt werden
Ll = [ x for x in L if x < p ]; Ll = [ x for x in L if x < p ];
Lr = [ x for x in L if x > p ]; Lr = [ x for x in L if x > p ];

View File

@ -39,7 +39,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM jump search # ALGORITHM jump search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Sprungsuche', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def JumpSearchLinear(L: List[int], x: int, m: int) -> int: def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, x = Zahl, m = lineare Sprunggröße. Inputs: L = Liste von Zahlen, x = Zahl, m = lineare Sprunggröße.
@ -52,7 +52,7 @@ def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
''' '''
i = 0; i = 0;
while i*m < len(L): while i*m < len(L):
AddToCounter(); AddTimeCost();
offset = i*m; offset = i*m;
block = L[offset:][:m]; block = L[offset:][:m];
elementAfterBlock = block[-1] + 1; elementAfterBlock = block[-1] + 1;
@ -70,7 +70,7 @@ def JumpSearchLinear(L: List[int], x: int, m: int) -> int:
# ALGORITHM jump search - exponentiell # ALGORITHM jump search - exponentiell
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sprungsuche (exponentiell)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Sprungsuche (exponentiell)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def JumpSearchExponentiell(L: List[int], x: int) -> int: def JumpSearchExponentiell(L: List[int], x: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, x = Zahl. Inputs: L = Liste von Zahlen, x = Zahl.
@ -84,7 +84,7 @@ def JumpSearchExponentiell(L: List[int], x: int) -> int:
i0 = 0; i0 = 0;
i1 = 1; i1 = 1;
while i0 < len(L): while i0 < len(L):
AddToCounter(); AddTimeCost();
block = L[i0:i1]; block = L[i0:i1];
elementAfterBlock = block[-1] + 1; elementAfterBlock = block[-1] + 1;
if x < elementAfterBlock: if x < elementAfterBlock:

View File

@ -21,23 +21,25 @@ from src.algorithms.methods import *;
# CHECKS # CHECKS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def preChecks(L: List[bool], **_): def preChecks(L: List[int], **_):
assert sum(L) > 0, 'Mindestens ein Getränk muss vergiftet sein!'; s = sum(L);
assert sum(L) == 1, 'Höchstens ein Getränk darf vergiftet sein!'; assert s > 0, 'Mindestens ein Getränk muss vergiftet sein!';
assert s <= 1, 'Höchstens ein Getränk darf vergiftet sein!';
return; return;
def postChecks(L: List[bool], index: int, **_): def postChecks(L: List[int], index: int, **_):
assert L[index] == True, 'Der Algorithmus hat das vergiftete Getränk nicht erfolgreich bestimmt.'; 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; return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ALGORITHM find poison # ALGORITHM find poison
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Giftsuche (O(n) Vorkoster)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def FindPoison(L: List[bool]) -> int: def FindPoison(L: List[int]) -> int:
''' '''
Inputs: L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist. 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. Annahme: Genau ein Getränk sei vergiftet.
Outputs: Der Index des vergifteten Getränks, falls es eines gibt, ansonsten -1. Outputs: Der Index des vergifteten Getränks, falls es eines gibt, ansonsten -1.
@ -47,7 +49,7 @@ def FindPoison(L: List[bool]) -> int:
n = len(L); n = len(L);
testers = []; testers = [];
for i in range(n): for i in range(n):
AddToCounter(); AddSpaceCost();
logDebug('Füge Vorkoster hinzu, der nur Getränk {i} testet.'.format(i=i)) logDebug('Füge Vorkoster hinzu, der nur Getränk {i} testet.'.format(i=i))
testers.append([i]); testers.append([i]);
logDebug('Warte auf Effekte'); logDebug('Warte auf Effekte');
@ -62,10 +64,10 @@ def FindPoison(L: List[bool]) -> int:
# ALGORITHM find poison fast # ALGORITHM find poison fast
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Giftsuche (O(log(n)) Vorkoster)', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def FindPoisonFast(L: List[bool]) -> List[int]: def FindPoisonFast(L: List[int]) -> int:
''' '''
Inputs: L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist. 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. Annahme: Genau ein Getränk sei vergiftet.
Outputs: Der Index des vergifteten Getränks, falls es eines gibt, ansonsten -1. Outputs: Der Index des vergifteten Getränks, falls es eines gibt, ansonsten -1.
@ -81,7 +83,7 @@ def FindPoisonFast(L: List[bool]) -> List[int]:
tester1 = [ k for k in range(n) if not (k in tester0) ]; 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. # 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. # Darum zählen wir nicht 2 sondern 1 Vorkoster.
AddToCounter(1); AddSpaceCost(1);
logDebug('Füge Vorkoster hinzu, der alle Getränke k testet mit {i}. Bit = 0.'.format(i=i)) logDebug('Füge Vorkoster hinzu, der alle Getränke k testet mit {i}. Bit = 0.'.format(i=i))
testers.append(tester0); testers.append(tester0);
testers.append(tester1); testers.append(tester1);
@ -97,10 +99,10 @@ def FindPoisonFast(L: List[bool]) -> List[int]:
# AUXILIARY METHOD wait for effects, evaluate effects # AUXILIARY METHOD wait for effects, evaluate effects
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def waitForEffects(L: List[bool], testers: List[List[int]]) -> List[int]: def waitForEffects(L: List[int], testers: List[List[int]]) -> List[int]:
''' '''
Inputs: Inputs:
- L = Liste von Getränken: durch boolesche Werte wird dargestellt, ob ein Getränk vergiftet ist. - 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. - 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. Outputs: effects = eine Liste, die jedem Vorkoster zuordnet, wie viele vergiftete Getränke er konsumiert hat.

View File

@ -37,7 +37,7 @@ def postChecks(L: List[int], x: int, index: int, **_):
# ALGORITHM sequential search # ALGORITHM sequential search
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames='index', checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='Sequenziellsuchalgorithmus', outputnames=['index'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def SequentialSearch(L: List[int], x: int) -> int: def SequentialSearch(L: List[int], x: int) -> int:
''' '''
Inputs: L = Liste von Zahlen, x = Zahl. Inputs: L = Liste von Zahlen, x = Zahl.
@ -45,7 +45,7 @@ def SequentialSearch(L: List[int], x: int) -> int:
''' '''
n = len(L); n = len(L);
for i in range(n): for i in range(n):
AddToCounter(); AddTimeCost();
if L[i] == x: if L[i] == x:
logDebug('Element in Position {} gefunden.'.format(i)); logDebug('Element in Position {} gefunden.'.format(i));
return i; return i;

View File

@ -33,7 +33,7 @@ def postChecks(L: List[int], **_):
# ALGORITHM max sub sum # ALGORITHM max sub sum
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=('maxSum', 'index_from', 'index_to'), checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='MaxSubSum (Maximale Teilsumme)', outputnames=['maxSum', 'index_from', 'index_to'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def MaxSubSum(L: List[float]) -> Tuple[float, int, int]: def MaxSubSum(L: List[float]) -> Tuple[float, int, int]:
''' '''
Inputs: L = Liste von Zahlen Inputs: L = Liste von Zahlen
@ -58,7 +58,7 @@ def MaxSubSum(L: List[float]) -> Tuple[float, int, int]:
# ALGORITHM max sub sum (D & C) # ALGORITHM max sub sum (D & C)
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@algorithmInfos(name='MaxSubSum (Maximale Teilsumme mit D & C)', outputnames=('maxSum', 'index_from', 'index_to'), checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks) @algorithmInfos(name='MaxSubSum (Maximale Teilsumme mit D & C)', outputnames=['maxSum', 'index_from', 'index_to'], checks=True, metrics=True, preChecks=preChecks, postChecks=postChecks)
def MaxSubSumDC(L: List[float]) -> Tuple[float, int, int]: def MaxSubSumDC(L: List[float]) -> Tuple[float, int, int]:
''' '''
Inputs: L = Liste von Zahlen Inputs: L = Liste von Zahlen
@ -127,7 +127,7 @@ def lRandSum(L: List[float]) -> Tuple[float, int, int]:
''' '''
n = len(L); n = len(L);
## berechne kumulative Summen (vorwärts) ## berechne kumulative Summen (vorwärts)
AddToCounter(n); AddTimeCost(n);
total = L[0]; total = L[0];
maxSum = total; maxSum = total;
u = 0; u = 0;
@ -148,7 +148,7 @@ def rRandSum(L: List[float]) -> Tuple[float, int, int]:
''' '''
n = len(L); n = len(L);
## berechne kumulative Summen (rückwärts) ## berechne kumulative Summen (rückwärts)
AddToCounter(n); AddTimeCost(n);
total = L[n-1]; total = L[n-1];
maxSum = total; maxSum = total;
u = n-1; u = n-1;

View File

@ -10,10 +10,6 @@ from src.local.misc import *;
from src.local.system import *; from src.local.system import *;
from src.local.typing import *; from src.local.typing import *;
from datetime import timedelta;
from src.core.metrics import *;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES # GLOBAL VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -21,7 +17,6 @@ from src.core.metrics import *;
_logging_prefix: str = ''; _logging_prefix: str = '';
_quietmode: bool = False; _quietmode: bool = False;
_debugmode: bool = False; _debugmode: bool = False;
_ctr: Counter = Counter();
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHOD get/set quiet mode, logging depth, timer # METHOD get/set quiet mode, logging depth, timer
@ -43,24 +38,6 @@ def SetDebugMode(mode: bool):
_debugmode = mode; _debugmode = mode;
return; return;
def RestartCounter():
global _ctr;
_ctr.reset();
return;
def AddToCounter(n: int = 1):
global _ctr;
_ctr.add(n);
return;
def NumberOfSteps() -> int:
return _ctr.numberOfStep;
def TimeElapsed() -> timedelta:
global _ctr;
_ctr.stop();
return _ctr.elapsedTime;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Logging # Logging
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -5,17 +5,24 @@
# IMPORTS # IMPORTS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
from __future__ import annotations;
from datetime import datetime; from datetime import datetime;
from datetime import timedelta; from datetime import timedelta;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBAL VARIABLES
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
_ctr_time = None;
_ctr_space = None;
_tmr = None;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CLASS counter # CLASS counter
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Counter(object): class Counter(object):
_nr_steps: int; _nr_steps: int;
_timeelapsed: timedelta;
_timecurrent: datetime;
def __init__(self): def __init__(self):
self.reset(); self.reset();
@ -27,27 +34,87 @@ class Counter(object):
def numberOfStep(self) -> int: def numberOfStep(self) -> int:
return self._nr_steps; return self._nr_steps;
@property
def elapsedTime(self) -> timedelta:
return self._timeelapsed;
def start(self):
self._timecurrent = datetime.now();
return self;
def stop(self):
t0 = self._timecurrent;
t1 = datetime.now();
self._timecurrent = t1;
self._timeelapsed += (t1 - t0);
return self;
def add(self, n: int = 1): def add(self, n: int = 1):
self._nr_steps += n; self._nr_steps += n;
return self; return self;
def reset(self): def reset(self):
t = datetime.now();
self._timeelapsed = t - t;
self._nr_steps = 0; self._nr_steps = 0;
self._timecurrent = t;
return self; return self;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# CLASS timer
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class Timer(object):
_time_elapsed: timedelta;
_time_current: datetime;
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();
return self;
def stop(self):
t0 = self._time_current;
t1 = datetime.now();
delta = t1 - t0;
self._time_current = t1;
self._time_elapsed += delta;
return self;
def reset(self):
t = datetime.now();
delta = t - t;
self._time_current = t;
self._time_elapsed = delta;
return self;
## Initialisierung:
_ctr_time = Counter();
_ctr_space = Counter();
_tmr = Timer();
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODS
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def RestartMetrics():
global _ctr_time;
global _ctr_space;
global _tmr;
_ctr_time.reset();
_ctr_space.reset();
_tmr.reset();
return;
def AddTimeCost(n: int = 1):
global _ctr_time;
_ctr_time.add(n);
return;
def AddSpaceCost(n: int = 1):
global _ctr_space;
_ctr_space.add(n);
return;
def GetTimeCost() -> int:
return _ctr_time.numberOfStep;
def GetSpaceCost() -> int:
return _ctr_space.numberOfStep;
def GetTimeElapsed() -> timedelta:
global _tmr;
_tmr.stop();
return _tmr.elapsedTime;

View File

@ -8,6 +8,7 @@
from src.local.typing import *; from src.local.typing import *;
from src.core.log import *; from src.core.log import *;
from src.core.metrics import *;
from src.setup.cli import GetArgumentParser; from src.setup.cli import GetArgumentParser;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -67,8 +68,9 @@ def DisplayEndOfAlgorithm(*_: Any, **outputs: Any):
return; return;
def DisplayMetrics(): def DisplayMetrics():
logPlain('Dauer der Ausführung: t = \033[1m{}\033[0m'.format(TimeElapsed())); logPlain('Dauer der Ausführung: t = \033[1m{}\033[0m'.format(GetTimeElapsed()));
logPlain('Anzahl der Schritte: T(n) = \033[1m{}\033[0m'.format(NumberOfSteps())); logPlain('Kosten (Zeit): T(n) = \033[1m{}\033[0m'.format(GetTimeCost()));
logPlain('Kosten (Platz): S(n) = \033[1m{}\033[0m'.format(GetSpaceCost()));
return; return;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~