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,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
}