Compare commits

...

5 Commits

23 changed files with 347 additions and 24 deletions

View File

@ -85,3 +85,7 @@ parts:
- command: 'algorithm-search-interpolation' - command: 'algorithm-search-interpolation'
description: 'Seminarblatt Woche 3, Aufgabe 1' description: 'Seminarblatt Woche 3, Aufgabe 1'
inputs: *ref_inputs_sem3_1 inputs: *ref_inputs_sem3_1
- command: 'algorithm-stacks-next-greater-element'
description: 'Seminarblatt Woche 4, Aufgabe 1'
inputs:
L: [4, 2, 1, 100, 6, 3, 16]

View File

@ -4,8 +4,8 @@
Dieses Projekt ist erneut kein nötiger Bestandteil des Kurses, Dieses Projekt ist erneut kein nötiger Bestandteil des Kurses,
sondern nur für Wissbegierige gedacht. sondern nur für Wissbegierige gedacht.
Zunächst bietet sich an, sich die Algorithmen im Unterordner [`internal/algorithms`](./internal/algorithms) anzuschauen, Zunächst bietet sich an, sich die Algorithmen im Unterordner [`pkg/algorithms`](./pkg/algorithms) anzuschauen,
z. B. [`internal/algorithms/search/binary/binary.go`](./internal/algorithms/search/binary/binary.go) für den Binärsuchalgorithmus, z. B. [`pkg/algorithms/search/binary/binary.go`](./pkg/algorithms/search/binary/binary.go) für den Binärsuchalgorithmus,
ohne irgendetwas installieren zu müssen. ohne irgendetwas installieren zu müssen.
**HINWEIS 1:** _Bei meiner Implementierung kann es zu leichten Abweichungen kommen. Bitte **stets** an dem Material im VL-Skript sich orientieren. Der Hauptzweck der Code-Projekte besteht darin, dass Wissbegierige die Algorithmen konkret ausprobieren können. Alle theoretischen Aspekte werden jedoch im Skript und in den Übungen ausführlicher erklärt._ **HINWEIS 1:** _Bei meiner Implementierung kann es zu leichten Abweichungen kommen. Bitte **stets** an dem Material im VL-Skript sich orientieren. Der Hauptzweck der Code-Projekte besteht darin, dass Wissbegierige die Algorithmen konkret ausprobieren können. Alle theoretischen Aspekte werden jedoch im Skript und in den Übungen ausführlicher erklärt._

View File

@ -11,13 +11,14 @@ import (
"ads/internal/setup" "ads/internal/setup"
"ads/internal/types" "ads/internal/types"
algorithm_search_binary "ads/internal/algorithms/search/binary" algorithm_search_binary "ads/pkg/algorithms/search/binary"
algorithm_search_interpol "ads/internal/algorithms/search/interpol" algorithm_search_interpol "ads/pkg/algorithms/search/interpol"
algorithm_search_ith_element "ads/internal/algorithms/search/ith_element" algorithm_search_ith_element "ads/pkg/algorithms/search/ith_element"
algorithm_search_jump "ads/internal/algorithms/search/jump" algorithm_search_jump "ads/pkg/algorithms/search/jump"
algorithm_search_poison "ads/internal/algorithms/search/poison" algorithm_search_poison "ads/pkg/algorithms/search/poison"
algorithm_search_sequential "ads/internal/algorithms/search/sequential" algorithm_search_sequential "ads/pkg/algorithms/search/sequential"
algorithm_sum_maxsubsum "ads/internal/algorithms/sum/maxsubsum" algorithm_stacks_next_greater_element "ads/pkg/algorithms/stacks/next_greater_element"
algorithm_sum_maxsubsum "ads/pkg/algorithms/sum/maxsubsum"
) )
/* ---------------------------------------------------------------- * /* ---------------------------------------------------------------- *
@ -138,6 +139,13 @@ func RunNonInteractive(path string) error {
} else { } else {
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command) err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
} }
case "algorithm-stacks-next-greater-element":
L := inputs.List
if L != nil {
_, err_case = algorithm_stacks_next_greater_element.FancyNextGreaterElement(*L)
} else {
err_case = fmt.Errorf("Fehlende Inputs für Befehl '%[1]s'.", *problem.Command)
}
case "algorithm-sum-maxsub": case "algorithm-sum-maxsub":
L := inputs.List L := inputs.List
if L != nil { if L != nil {

View File

@ -8,17 +8,18 @@ import (
"ads/internal/core/logging" "ads/internal/core/logging"
"ads/internal/setup" "ads/internal/setup"
algorithm_search_binary "ads/internal/algorithms/search/binary" algorithm_search_binary "ads/pkg/algorithms/search/binary"
algorithm_search_interpol "ads/internal/algorithms/search/interpol" algorithm_search_interpol "ads/pkg/algorithms/search/interpol"
algorithm_search_ith_element "ads/internal/algorithms/search/ith_element" algorithm_search_ith_element "ads/pkg/algorithms/search/ith_element"
algorithm_search_jump "ads/internal/algorithms/search/jump" algorithm_search_jump "ads/pkg/algorithms/search/jump"
algorithm_search_poison "ads/internal/algorithms/search/poison" algorithm_search_poison "ads/pkg/algorithms/search/poison"
algorithm_search_sequential "ads/internal/algorithms/search/sequential" algorithm_search_sequential "ads/pkg/algorithms/search/sequential"
algorithm_sum_maxsubsum "ads/internal/algorithms/sum/maxsubsum" algorithm_stacks_next_greater_element "ads/pkg/algorithms/stacks/next_greater_element"
algorithm_sum_maxsubsum "ads/pkg/algorithms/sum/maxsubsum"
) )
/* ---------------------------------------------------------------- * /* ---------------------------------------------------------------- *
* ACTIONS - Algorithmen * ACTIONS algorithmen - search
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */
func actionAlgorithmSearchBinary() (bool, error) { func actionAlgorithmSearchBinary() (bool, error) {
@ -202,6 +203,28 @@ func actionAlgorithmSearchSequential() (bool, error) {
return cancel, nil return cancel, nil
} }
/* ---------------------------------------------------------------- *
* ACTIONS algorithmen - stacks
* ---------------------------------------------------------------- */
func actionAlgorithmStacksNextGreaterElement() (bool, error) {
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
if cancel || err != nil {
return cancel, err
}
setup.DisplayStartOfCaseBlank()
_, err = algorithm_stacks_next_greater_element.FancyNextGreaterElement(input_L)
if err != nil {
logging.Error(err)
}
setup.DisplayEndOfCase()
return cancel, nil
}
/* ---------------------------------------------------------------- *
* ACTIONS algorithmen - sum
* ---------------------------------------------------------------- */
func actionAlgorithmSumMaxsub() (bool, error) { func actionAlgorithmSumMaxsub() (bool, error) {
input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{}) input_L, cancel, err := promptInputListOfInt("L", "Liste von Werten", []string{})
if cancel || err != nil { if cancel || err != nil {

View File

@ -27,6 +27,7 @@ var menuMain = menus.Menu{
}, { }, {
{Label: "Suchalgorithmen", Submenu: &menuSearchAlgorithms}, {Label: "Suchalgorithmen", Submenu: &menuSearchAlgorithms},
{Label: "Summenalgorithmen", Submenu: &menuSumAlgorithms}, {Label: "Summenalgorithmen", Submenu: &menuSumAlgorithms},
{Label: "Algorithmen mit Stacks und Queues", Submenu: &menuStacksQueuesAlgorithms},
}, },
}, },
Default: -1, Default: -1,
@ -117,6 +118,19 @@ var menuSearchAlgorithms = menus.Menu{
Default: -1, Default: -1,
} }
var menuStacksQueuesAlgorithms = menus.Menu{
Path: []string{"Hauptmenü", "Algorithmen mit Stacks und Queues"},
PromptMessages: []string{
"Algorithmus wählen",
},
Options: [][]menus.MenuOption{
{
{Label: "'Next Greater Element' mit Stacks", Action: actionAlgorithmStacksNextGreaterElement},
},
},
Default: -1,
}
var menuSumAlgorithms = menus.Menu{ var menuSumAlgorithms = menus.Menu{
Path: []string{"Hauptmenü", "Summenalgorithmen"}, Path: []string{"Hauptmenü", "Summenalgorithmen"},
PromptMessages: []string{ PromptMessages: []string{

View File

@ -103,8 +103,8 @@ func DisplayEndOfAlgorithm(outputs map[string]interface{}) {
func DisplayMetrics() { func DisplayMetrics() {
// logging.Plain("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsed()) // logging.Plain("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsed())
logging.Plain("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsedLongFormat()) logging.Plain("Dauer der Ausführung: t = \033[1m%[1]v\033[0m", metrics.GetTimeElapsedLongFormat())
logging.Plain("Kosten (Zeit): T(n) = \033[1m%[1]v\033[0m", metrics.GetTimeCost()) logging.Plain("Kosten (Zeit): T(n) = \033[1m%[1]v\033[0m", displayCost(metrics.GetTimeCost()))
logging.Plain("Kosten (Platz): S(n) = \033[1m%[1]v\033[0m", metrics.GetSpaceCost()) logging.Plain("Kosten (Platz): S(n) = \033[1m%[1]v\033[0m", displayCost(metrics.GetSpaceCost()))
return return
} }
@ -120,3 +120,10 @@ func DisplayBar(options ...int) {
logging.Plain("+%[1]s+", strings.Repeat("-", n)) logging.Plain("+%[1]s+", strings.Repeat("-", n))
return return
} }
func displayCost(cost int) string {
if cost > 0 {
return fmt.Sprintf("%v", cost)
}
return "-"
}

View File

@ -38,15 +38,14 @@ func InterpolationSearch(L []int, x int, u int, v int) int {
} }
metrics.AddTimeCost() metrics.AddTimeCost()
p := getSuchposition(L, x, u, v) p := getSuchposition(L, x, u, v)
logging.Debug("Interpolante von x in (u, v)=(%[1]v, %[2]v) ist p = %[3]v.", u, v, p)
if L[p] == x { if L[p] == x {
logging.Debug("x in Position p gefunden") logging.Debug("Interpolante in (%[1]v, %[2]v) ist p = %[3]v; L[p] == x; ===> Element gefunden", u, v, p)
return p return p
} else if x < L[p] { } else if x < L[p] {
logging.Debug("Suche in linker Hälfte fortsetzen.") logging.Debug("Interpolante in (%[1]v, %[2]v) ist p = %[3]v; L[p] > x; ===> suche in linker Hälfte", u, v, p)
return InterpolationSearch(L, x, u, p-1) return InterpolationSearch(L, x, u, p-1)
} else { // } else if x > L[p] { } else { // } else if x > L[p] {
logging.Debug("Suche in rechter Hälfte fortsetzen.") logging.Debug("Interpolante in (%[1]v, %[2]v) ist p = %[3]v; L[p] < x; ===> suche in rechter Hälfte", u, v, p)
return InterpolationSearch(L, x, p+1, v) return InterpolationSearch(L, x, p+1, v)
} }
} }

View File

@ -5,9 +5,9 @@ package jump
* ---------------------------------------------------------------- */ * ---------------------------------------------------------------- */
import ( import (
"ads/internal/algorithms/search/sequential"
"ads/internal/core/logging" "ads/internal/core/logging"
"ads/internal/core/metrics" "ads/internal/core/metrics"
"ads/pkg/algorithms/search/sequential"
) )
/* ---------------------------------------------------------------- * /* ---------------------------------------------------------------- *

View File

@ -0,0 +1,107 @@
package next_greater_element
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"ads/internal/core/logging"
"ads/internal/core/metrics"
"ads/pkg/data_structures/stacks"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES/CONSTANTS
* ---------------------------------------------------------------- */
var _output_list [][2]int
/* ---------------------------------------------------------------- *
* ALGORITHM next greater element
* ---------------------------------------------------------------- */
/*
Inputs: L = Liste von Zahlen, x = Zahl.
Outputs: Liste von Paaren von Elementen und ihrem nächsten größeren Element
*/
func NextGreaterElement(L []int) [][2]int {
clearOutput()
if len(L) == 0 {
return output()
}
S := stacks.CREATE()
for i := 0; i < len(L); i++ {
logging.Debug("Lies Element L[%v] ein", i)
nextElement := L[i]
logging.Debug("Stack S | %v", S)
if !S.EMPTY() {
logging.Debug("Entferne alle top Elemente vom Stack bis >= nextElement")
element := S.TOP()
S.POP()
metrics.AddTimeCost()
/*
Entferne kleinere Elemente vom Stack
Aktuelles Element ist jeweils größerer rechter Partner
*/
for element < nextElement {
logging.Debug("Stack S | %v", S)
addToOutput(element, nextElement)
if S.EMPTY() {
break
}
element = S.TOP()
S.POP()
metrics.AddTimeCost()
}
// lege letztes Element zurück
if element > nextElement {
logging.Debug("Element >= nextElement zurücklegen")
S.PUSH(element)
metrics.AddTimeCost()
}
logging.Debug("Stack S | %v", S)
}
S.PUSH(nextElement)
metrics.AddTimeCost()
logging.Debug("L[%v] auf Stack legen", i)
logging.Debug("Stack S | %v", S)
}
// was übrig bleibt hat kein größeres Element
logging.Debug("Alles übrige auf Stack hat kein nächstes größeres Element")
for !S.EMPTY() {
metrics.AddTimeCost()
logging.Debug("Stack S | %v", S)
element := S.TOP()
S.POP()
addToOutput(element, -1)
}
logging.Debug("Stack S | %v", S)
return output()
}
/* ---------------------------------------------------------------- *
* AUXILIARY METHODS
* ---------------------------------------------------------------- */
func clearOutput() {
_output_list = [][2]int{}
}
func addToOutput(m int, n int) {
_output_list = append(_output_list, [2]int{m, n})
}
func output() [][2]int {
var output = make([][2]int, len(_output_list))
copy(output, _output_list)
clearOutput()
return output
}

View File

@ -0,0 +1,89 @@
package next_greater_element
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"ads/internal/core/metrics"
"ads/internal/setup"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES/CONSTANTS
* ---------------------------------------------------------------- */
//
/* ---------------------------------------------------------------- *
* CHECKS
* ---------------------------------------------------------------- */
func preChecks(L []int, _ ...interface{}) error {
// TODO
return nil
}
func postChecks(L []int, pairs [][2]int, _ ...interface{}) error {
// TODO
return nil
}
/* ---------------------------------------------------------------- *
* ALGORITHM binary search + Display
* ---------------------------------------------------------------- */
func FancyNextGreaterElement(input_L []int) ([][2]int, error) {
var name = "Binärsuchalgorithmus"
var inputs = map[string]interface{}{
"L": input_L,
}
var outputs map[string]interface{}
var (
pairs [][2]int
)
var err error
do_once := true
for do_once {
do_once = false
// Start Message
setup.DisplayStartOfAlgorithm(name, inputs)
// Prechecks:
if setup.AppConfigPerformChecks() {
err = preChecks(input_L)
if err != nil {
break
}
}
// Ausführung des Algorithmus:
metrics.ResetMetrics()
metrics.StartMetrics()
pairs = NextGreaterElement(input_L)
metrics.StopMetrics()
outputs = map[string]interface{}{
"pairs": pairs,
}
// Metriken anzeigen
if setup.AppConfigShowMetrics() {
setup.DisplayMetrics()
}
// End Message
setup.DisplayEndOfAlgorithm(outputs)
// Postchecks:
if setup.AppConfigPerformChecks() {
err = postChecks(input_L, pairs)
if err != nil {
break
}
}
}
return pairs, err
}

View File

@ -0,0 +1,72 @@
package stacks
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"strings"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES/CONSTANTS
* ---------------------------------------------------------------- */
//
/* ---------------------------------------------------------------- *
* TYPE
* ---------------------------------------------------------------- */
type StackInt struct {
values []int
}
/* ---------------------------------------------------------------- *
* METHODS stacks
* ---------------------------------------------------------------- */
func CREATE() StackInt {
return StackInt{
values: []int{},
}
}
func (S *StackInt) INIT() StackInt {
return StackInt{
values: []int{},
}
}
func (S StackInt) EMPTY() bool {
return len(S.values) == 0
}
func (S *StackInt) PUSH(x int) {
S.values = append(S.values, x)
}
func (S *StackInt) TOP() int {
if S.EMPTY() {
panic("Cannot pop from empty stack!")
}
return S.values[len(S.values)-1]
}
func (S *StackInt) POP() int {
x := S.TOP()
S.values = S.values[:(len(S.values) - 1)]
return x
}
func (S StackInt) String() string {
if len(S.values) == 0 {
return "-"
}
values := []string{}
for _, value := range S.values {
values = append(values, fmt.Sprintf("%v", value))
}
return fmt.Sprintf(strings.Join(values, ", "))
}