diff --git a/go.mod b/go.mod index 0c34830..b531060 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,5 @@ module github.com/amwolff/gorder -go 1.16 +go 1.20 require github.com/davecgh/go-spew v1.1.1 diff --git a/gorder.go b/gorder.go index 4bad6e4..06bce74 100644 --- a/gorder.go +++ b/gorder.go @@ -5,7 +5,7 @@ import ( "regexp" ) -func TopologicalSort(digraph map[interface{}][]interface{}, algorithm string) (solution []interface{}, err error) { +func TopologicalSort[T comparable, V []T](digraph map[T]V, algorithm string) (solution V, err error) { kahnRgxp, err := regexp.Compile(`[Kk]ahn\z`) if err != nil { return nil, err @@ -29,24 +29,24 @@ func TopologicalSort(digraph map[interface{}][]interface{}, algorithm string) (s return solution, nil } -func kahn(digraph map[interface{}][]interface{}) ([]interface{}, error) { - indegrees := make(map[interface{}]int) - for u := range digraph { - if digraph[u] != nil { - for _, v := range digraph[u] { - indegrees[v]++ - } +func kahn[T comparable, V []T](digraph map[T]V) (V, error) { + indegrees := make(map[T]int) + + // loop through all diagraph and add increase indegrees of values + for _, iter := range digraph { + for _, v := range iter { + indegrees[v]++ } } - var queue []interface{} + var queue V for u := range digraph { if _, ok := indegrees[u]; !ok { queue = append(queue, u) } } - var order []interface{} + var order V for len(queue) > 0 { u := queue[len(queue)-1] queue = queue[:(len(queue) - 1)] @@ -67,16 +67,16 @@ func kahn(digraph map[interface{}][]interface{}) ([]interface{}, error) { return order, nil } -func dfsBased(digraph map[interface{}][]interface{}) ([]interface{}, error) { +func dfsBased[T comparable, V []T](digraph map[T]V) (V, error) { var ( acyclic = true - order []interface{} - permanentMark = make(map[interface{}]bool) - temporaryMark = make(map[interface{}]bool) - visit func(interface{}) + order V + permanentMark = make(map[T]bool) + temporaryMark = make(map[T]bool) + visit func(T) ) - visit = func(u interface{}) { + visit = func(u T) { if temporaryMark[u] { acyclic = false } else if !(temporaryMark[u] || permanentMark[u]) { @@ -89,7 +89,7 @@ func dfsBased(digraph map[interface{}][]interface{}) ([]interface{}, error) { } delete(temporaryMark, u) permanentMark[u] = true - order = append([]interface{}{u}, order...) + order = append(V{u}, order...) } } diff --git a/gorder_test.go b/gorder_test.go index b2a8f3e..6093f3b 100644 --- a/gorder_test.go +++ b/gorder_test.go @@ -7,10 +7,10 @@ import ( ) func TestTopologicalSort(t *testing.T) { - digraph := map[interface{}][]interface{}{ - 1: []interface{}{2, 4}, - 2: []interface{}{3, 5}, - 3: []interface{}{4, 5}, + digraph := map[int][]int{ + 1: {2, 4}, + 2: {3, 5}, + 3: {4, 5}, } want := []int{1, 2, 3, 5, 4} @@ -40,11 +40,11 @@ func TestTopologicalSort(t *testing.T) { } } - graphWithCycles := map[interface{}][]interface{}{ - 1: []interface{}{2, 4}, - 2: []interface{}{3, 5}, - 3: []interface{}{4, 5}, - 4: []interface{}{2}, + graphWithCycles := map[int][]int{ + 1: {2, 4}, + 2: {3, 5}, + 3: {4, 5}, + 4: {2}, } _, err = TopologicalSort(graphWithCycles, "kahn") if err == nil {