package maxsubsum /* ---------------------------------------------------------------- * * IMPORTS * ---------------------------------------------------------------- */ import ( "ads/internal/core/logging" "ads/internal/core/metrics" "ads/internal/core/utils" ) /* ---------------------------------------------------------------- * * GLOBAL VARIABLES/CONSTANTS * ---------------------------------------------------------------- */ // /* ---------------------------------------------------------------- * * ALGORITHM max sub sum * ---------------------------------------------------------------- */ /* Inputs: L = Liste von Zahlen Outputs: - maxSum = Wert der maximalen Summe einer Teilliste aufeinanderfolgender Elemente - u, v = Indexes so dass die Teilliste [L[u], L[u+1], ..., L[v]] die maximale Summe aufweist */ func MaxSubSum(L []int) (int, int, int) { maxSum := 0 u := 0 v := -1 for i := 0; i < len(L); i++ { // Bestimme maximale Teilsumme der linken Rände der Liste ab Index i { maxSum_, _, k := lRandSum(L[i:]) if maxSum_ > maxSum { k += i // NOTE: muss wegen Offset kompensieren maxSum, u, v = maxSum_, i, k logging.Debug("max Teilsumme aktualisiert: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum) } } return maxSum, u, v } /* ---------------------------------------------------------------- * * ALGORITHM max sub sum (D & C) * ---------------------------------------------------------------- */ /* Inputs: L = Liste von Zahlen Outputs: - maxSum = Wert der maximalen Summe einer Teilliste aufeinanderfolgender Elemente - u, v = Indexes so dass die Teilliste [L[u], L[u+1], ..., L[v]] die maximale Summe aufweist */ func MaxSubSumDC(L []int) (int, int, int) { maxSum := 0 u := 0 v := -1 if len(L) == 1 { // wenn Liste aus 1 Element besteht, nicht teilen: if L[0] > maxSum { v = 0 maxSum = L[0] } } else { u = utils.Ceil(float64(len(L)) / 2) Ll := L[:u] Lr := L[u:] // berechnet maximale Teilsumme der linken Hälfte: maxSum1, u1, v1 := MaxSubSumDC(Ll) // berechnet maximale Teilsumme der rechten Hälfte: maxSum2, u2, v2 := MaxSubSumDC(Lr) u2, v2 = u2+len(Ll), v2+len(Ll) // offsets kompensieren // berechnet maximale Teilsumme mit Überschneidung zw. den Hälften: maxSum3, u3, v3 := lrRandSum(Ll, Lr) // bestimme Maximum der 3 Möglichkeiten: maxSum = utils.MaxInt(maxSum1, maxSum2, maxSum3) if maxSum == maxSum1 { maxSum, u, v = maxSum1, u1, v1 logging.Debug("max Teilsumme kommt in linker Partition vor: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum) } else if maxSum == maxSum3 { maxSum, u, v = maxSum3, u3, v3 logging.Debug("max Teilsumme kommt in Überschneidung vor: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum) } else { // } else if maxSum == maxSum2 { maxSum, u, v = maxSum2, u2, v2 logging.Debug("max Teilsumme kommt in rechter Partition vor: Summe L[i] von i=%[1]v .. %[2]v = %[3]v", u, v, maxSum) } } return maxSum, u, v } /* ---------------------------------------------------------------- * * AUXILIARY METHODS * ---------------------------------------------------------------- */ /* Bestimmt maximale Teilsumme einer Teiliste einer Liste, wobei die Liste in zwei Intervalle partitioniert ist und die Teilliste beide überschneidet. Inputs: Ll, Lr = eine Partition einer Liste von Zahlen in zwei Intervalle Outputs: maxSum, u=0, v */ func lrRandSum(Ll []int, Lr []int) (int, int, int) { maxSumL, u, _ := rRandSum(Ll) maxSumR, _, v := lRandSum(Lr) maxSum := maxSumL + maxSumR v += len(Ll) // offsets kompensieren return maxSum, u, v } /* Bestimmt maximale Teilsumme aller nicht leeren linken Segmente einer Liste. Inputs: L = Liste von Zahlen Outputs: maxSum, u(=0), v */ func lRandSum(L []int) (int, int, int) { n := len(L) // berechne kumulative Summen (vorwärts) metrics.AddTimeCost(n) total := L[0] maxSum := total u := 0 v := 0 for i := 0; i < n; i++ { total += L[i] if total > maxSum { v = i maxSum = total } } return maxSum, u, v } /* Bestimmt maximale Teilsumme aller nicht leeren rechten Segmente einer Liste. Inputs: L = Liste von Zahlen Outputs: maxSum, u, v(=len(L)-1) */ func rRandSum(L []int) (int, int, int) { n := len(L) // berechne kumulative Summen (rückwärts) metrics.AddTimeCost(n) total := L[n-1] maxSum := total u := n - 1 v := n - 1 for i := n - 2; i >= 0; i-- { total += L[i] if total > maxSum { u = i maxSum = total } } return maxSum, u, v }