master > master: src go - algorithmen + display methoden hinzugefügt

This commit is contained in:
RD 2021-11-01 19:58:55 +01:00
parent 2c23f4c728
commit a38f18ee81
24 changed files with 2304 additions and 19 deletions

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
}
// 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
m := map[string]bool{}
X_unique := []string{}
m := map[int]bool{}
X_unique := []int{}
for _, x := range X {
if _, ok = m[x]; !ok {
X_unique = append(X_unique, x)
@ -52,6 +67,10 @@ func UniqueListOfStrings(X []string) []string {
return X_unique
}
func ContainsNoDuplicatesListInt(X []int) bool {
return len(X) <= len(UniqueListInt(X))
}
/* ---------------------------------------------------------------- *
* 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 (
"ads/internal/core/logging"
"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
* ---------------------------------------------------------------- */
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.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
}

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"`
}