diff --git a/.github/workflows/godocmd.yml b/.github/workflows/godocmd.yml index 3b4f0ef4c..b69bf13d9 100644 --- a/.github/workflows/godocmd.yml +++ b/.github/workflows/godocmd.yml @@ -9,10 +9,10 @@ jobs: fetch-depth: 0 - uses: actions/setup-go@v2 with: - go-version: '^1.17' + go-version: '^1.18' - name: Install GoDocMD run: | - go install github.com/tjgurwara99/godocmd@v0.1.2 + go install github.com/tjgurwara99/godocmd@v0.1.3 - name: Configure Github Action run: | git config --global user.name github-action diff --git a/.github/workflows/golang_lint_and_test.yml b/.github/workflows/golang_lint_and_test.yml index 4cb59f712..29a2a9283 100644 --- a/.github/workflows/golang_lint_and_test.yml +++ b/.github/workflows/golang_lint_and_test.yml @@ -15,6 +15,8 @@ jobs: skip: "go.mod,go.sum" - name: Setup Go uses: actions/setup-go@v2 + with: + go-version: '^1.18' - name: Run Golang CI Lint uses: golangci/golangci-lint-action@v2 with: diff --git a/README.md b/README.md index 676a85def..da8fb416b 100644 --- a/README.md +++ b/README.md @@ -859,22 +859,23 @@ Read our [Contribution Guidelines](CONTRIBUTING.md) before you contribute. --- ##### Functions: -1. [`Comb`](./sort/combSort.go#L14): No description provided. -2. [`Count`](./sort/countingsort.go#L9): No description provided. -3. [`Exchange`](./sort/exchangesort.go#L6): No description provided. -4. [`HeapSort`](./sort/heapsort.go#L121): No description provided. -5. [`ImprovedSimpleSort`](./sort/simplesort.go#L25): ImprovedSimpleSort is a improve SimpleSort by skipping an unnecessary comparison of the first and last. This improved version is more similar to implementation of insertion sort -6. [`InsertionSort`](./sort/insertionsort.go#L3): No description provided. -7. [`MergeIter`](./sort/mergesort.go#L51): No description provided. -8. [`Mergesort`](./sort/mergesort.go#L37): Mergesort Perform mergesort on a slice of ints -9. [`Partition`](./sort/quicksort.go#L10): No description provided. -10. [`Pigeonhole`](./sort/pigeonholesort.go#L12): Pigeonhole sorts a slice using pigeonhole sorting algorithm. -11. [`QuickSort`](./sort/quicksort.go#L37): QuickSort Sorts the entire array -12. [`QuickSortRange`](./sort/quicksort.go#L24): QuickSortRange Sorts the specified range within the array -13. [`RadixSort`](./sort/radixsort.go#L35): No description provided. -14. [`SelectionSort`](./sort/selectionsort.go#L3): No description provided. -15. [`ShellSort`](./sort/shellsort.go#L3): No description provided. -16. [`SimpleSort`](./sort/simplesort.go#L11): No description provided. +1. [`Bubble`](./sort/bubblesort.go#L9): Bubble is a simple generic definition of Bubble sort algorithm. +2. [`Comb`](./sort/combSort.go#L17): Comb is a simple sorting algorithm which is an improvement of the bubble sorting algorithm. +3. [`Count`](./sort/countingsort.go#L11): No description provided. +4. [`Exchange`](./sort/exchangesort.go#L8): No description provided. +5. [`HeapSort`](./sort/heapsort.go#L121): No description provided. +6. [`ImprovedSimple`](./sort/simplesort.go#L27): ImprovedSimple is a improve SimpleSort by skipping an unnecessary comparison of the first and last. This improved version is more similar to implementation of insertion sort +7. [`Insertion`](./sort/insertionsort.go#L5): No description provided. +8. [`Merge`](./sort/mergesort.go#L40): Merge Perform merge sort on a slice +9. [`MergeIter`](./sort/mergesort.go#L54): No description provided. +10. [`Partition`](./sort/quicksort.go#L12): No description provided. +11. [`Pigeonhole`](./sort/pigeonholesort.go#L12): Pigeonhole sorts a slice using pigeonhole sorting algorithm. +12. [`Quicksort`](./sort/quicksort.go#L39): Quicksort Sorts the entire array +13. [`QuicksortRange`](./sort/quicksort.go#L26): QuicksortRange Sorts the specified range within the array +14. [`RadixSort`](./sort/radixsort.go#L35): No description provided. +15. [`Selection`](./sort/selectionsort.go#L5): No description provided. +16. [`Shell`](./sort/shellsort.go#L5): No description provided. +17. [`Simple`](./sort/simplesort.go#L13): No description provided. --- ##### Types diff --git a/constraints/contraints.go b/constraints/contraints.go new file mode 100644 index 000000000..ca902cec5 --- /dev/null +++ b/constraints/contraints.go @@ -0,0 +1,40 @@ +// Package constraints has some useful generic type constraints defined which is very similar to +// [golang.org/x/exp/constraints](https://pkg.go.dev/golang.org/x/exp/constraints) package. +// We refrained from using that until it gets placed into the standard library - currently +// there are some questions regarding this package [ref](https://github.com/golang/go/issues/50792). +package constraints + +// Signed is a generic type constraint for all signed integers. +type Signed interface { + ~int | ~int8 | ~int16 | ~int32 | ~int64 +} + +// Unsigned is a generic type constraint for all unsigned integers. +type Unsigned interface { + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 +} + +// Integer is a generic type constraint for all integers (signed and unsigned.) +type Integer interface { + Signed | Unsigned +} + +// Float is a generic type constraint for all floating point types. +type Float interface { + ~float32 | ~float64 +} + +// Number is a generic type constraint for all numeric types in Go except Complex types. +type Number interface { + Integer | Float +} + +// Ordered is a generic type constraint for all ordered data types in Go. +// Loosely speaking, in mathematics a field is an ordered field if there is a "total +// order" (a binary relation - in this case `<` symbol) such that we will always have +// if a < b then a + c < b + c and if 0 < a, 0 < b then 0 < a.b +// The idea in Go is quite similar, though only limited to Go standard types +// not user defined types. +type Ordered interface { + Integer | ~string | Float +} diff --git a/go.mod b/go.mod index e7de82f0c..23f37df27 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/TheAlgorithms/Go -go 1.17 +go 1.18 diff --git a/sort/bubblesort.go b/sort/bubblesort.go index 83242e5c5..4c40678b7 100644 --- a/sort/bubblesort.go +++ b/sort/bubblesort.go @@ -3,7 +3,10 @@ package sort -func bubbleSort(arr []int) []int { +import "github.com/TheAlgorithms/Go/constraints" + +// Bubble is a simple generic definition of Bubble sort algorithm. +func Bubble[T constraints.Ordered](arr []T) []T { swapped := true for swapped { swapped = false diff --git a/sort/combSort.go b/sort/combSort.go index fa7b173d9..76e523e34 100644 --- a/sort/combSort.go +++ b/sort/combSort.go @@ -3,6 +3,8 @@ package sort +import "github.com/TheAlgorithms/Go/constraints" + func getNextGap(gap int) int { gap = (gap * 10) / 13 if gap < 1 { @@ -11,7 +13,8 @@ func getNextGap(gap int) int { return gap } -func Comb(data []int) []int { +// Comb is a simple sorting algorithm which is an improvement of the bubble sorting algorithm. +func Comb[T constraints.Ordered](data []T) []T { n := len(data) gap := n swapped := true diff --git a/sort/countingsort.go b/sort/countingsort.go index 3dae5934a..6961efff8 100644 --- a/sort/countingsort.go +++ b/sort/countingsort.go @@ -6,11 +6,13 @@ package sort -func Count(data []int) []int { +import "github.com/TheAlgorithms/Go/constraints" + +func Count[T constraints.Number](data []int) []int { var aMin, aMax = -1000, 1000 count := make([]int, aMax-aMin+1) for _, x := range data { - count[x-aMin]++ + count[x-aMin]++ // this is the reason for having only Number constraint instead of Ordered. } z := 0 for i, c := range count { diff --git a/sort/exchangesort.go b/sort/exchangesort.go index b901490cb..cbf6b9b00 100644 --- a/sort/exchangesort.go +++ b/sort/exchangesort.go @@ -3,7 +3,9 @@ package sort -func Exchange(arr []int) []int { +import "github.com/TheAlgorithms/Go/constraints" + +func Exchange[T constraints.Ordered](arr []T) []T { for i := 0; i < len(arr)-1; i++ { for j := i + 1; j < len(arr); j++ { if arr[i] > arr[j] { diff --git a/sort/insertionsort.go b/sort/insertionsort.go index 11f0cd922..b51bc5379 100644 --- a/sort/insertionsort.go +++ b/sort/insertionsort.go @@ -1,6 +1,8 @@ package sort -func InsertionSort(arr []int) []int { +import "github.com/TheAlgorithms/Go/constraints" + +func Insertion[T constraints.Ordered](arr []T) []T { for currentIndex := 1; currentIndex < len(arr); currentIndex++ { temporary := arr[currentIndex] iterator := currentIndex diff --git a/sort/mergesort.go b/sort/mergesort.go index 45c17ab04..babff39f1 100644 --- a/sort/mergesort.go +++ b/sort/mergesort.go @@ -1,10 +1,13 @@ package sort -import "github.com/TheAlgorithms/Go/math/min" +import ( + "github.com/TheAlgorithms/Go/constraints" + "github.com/TheAlgorithms/Go/math/min" +) -func merge(a []int, b []int) []int { +func merge[T constraints.Ordered](a []T, b []T) []T { - var r = make([]int, len(a)+len(b)) + var r = make([]T, len(a)+len(b)) var i = 0 var j = 0 @@ -33,8 +36,8 @@ func merge(a []int, b []int) []int { } -//Mergesort Perform mergesort on a slice of ints -func Mergesort(items []int) []int { +// Merge Perform merge sort on a slice +func Merge[T constraints.Ordered](items []T) []T { if len(items) < 2 { return items @@ -42,13 +45,13 @@ func Mergesort(items []int) []int { } var middle = len(items) / 2 - var a = Mergesort(items[:middle]) - var b = Mergesort(items[middle:]) + var a = Merge(items[:middle]) + var b = Merge(items[middle:]) return merge(a, b) } -func MergeIter(items []int) []int { +func MergeIter[T constraints.Ordered](items []T) []T { for step := 1; step < len(items); step += step { for i := 0; i+step < len(items); i += 2 * step { tmp := merge(items[i:i+step], items[i+step:min.Int(i+2*step, len(items))]) diff --git a/sort/quicksort.go b/sort/quicksort.go index 36319cbea..576db395a 100644 --- a/sort/quicksort.go +++ b/sort/quicksort.go @@ -7,7 +7,9 @@ package sort -func Partition(arr []int, low, high int) int { +import "github.com/TheAlgorithms/Go/constraints" + +func Partition[T constraints.Ordered](arr []T, low, high int) int { index := low - 1 pivotElement := arr[high] for i := low; i < high; i++ { @@ -20,21 +22,21 @@ func Partition(arr []int, low, high int) int { return index + 1 } -// QuickSortRange Sorts the specified range within the array -func QuickSortRange(arr []int, low, high int) { +// QuicksortRange Sorts the specified range within the array +func QuicksortRange[T constraints.Ordered](arr []T, low, high int) { if len(arr) <= 1 { return } if low < high { pivot := Partition(arr, low, high) - QuickSortRange(arr, low, pivot-1) - QuickSortRange(arr, pivot+1, high) + QuicksortRange(arr, low, pivot-1) + QuicksortRange(arr, pivot+1, high) } } -// QuickSort Sorts the entire array -func QuickSort(arr []int) []int { - QuickSortRange(arr, 0, len(arr)-1) +// Quicksort Sorts the entire array +func Quicksort[T constraints.Ordered](arr []T) []T { + QuicksortRange(arr, 0, len(arr)-1) return arr } diff --git a/sort/selectionsort.go b/sort/selectionsort.go index 95fd4ffa1..b86000a9b 100644 --- a/sort/selectionsort.go +++ b/sort/selectionsort.go @@ -1,7 +1,8 @@ package sort -func SelectionSort(arr []int) []int { +import "github.com/TheAlgorithms/Go/constraints" +func Selection[T constraints.Ordered](arr []T) []T { for i := 0; i < len(arr); i++ { min := i for j := i + 1; j < len(arr); j++ { diff --git a/sort/shellsort.go b/sort/shellsort.go index 28f76dcae..fb04f6f7c 100644 --- a/sort/shellsort.go +++ b/sort/shellsort.go @@ -1,6 +1,8 @@ package sort -func ShellSort(arr []int) []int { +import "github.com/TheAlgorithms/Go/constraints" + +func Shell[T constraints.Ordered](arr []T) []T { for d := int(len(arr) / 2); d > 0; d /= 2 { for i := d; i < len(arr); i++ { for j := i; j >= d && arr[j-d] > arr[j]; j -= d { diff --git a/sort/simplesort.go b/sort/simplesort.go index 39f3a55f9..ec54c1db0 100644 --- a/sort/simplesort.go +++ b/sort/simplesort.go @@ -8,7 +8,9 @@ package sort -func SimpleSort(arr []int) []int { +import "github.com/TheAlgorithms/Go/constraints" + +func Simple[T constraints.Ordered](arr []T) []T { for i := 0; i < len(arr); i++ { for j := 0; j < len(arr); j++ { if arr[i] < arr[j] { @@ -20,9 +22,9 @@ func SimpleSort(arr []int) []int { return arr } -// ImprovedSimpleSort is a improve SimpleSort by skipping an unnecessary comparison of the first and last. +// ImprovedSimple is a improve SimpleSort by skipping an unnecessary comparison of the first and last. // This improved version is more similar to implementation of insertion sort -func ImprovedSimpleSort(arr []int) []int { +func ImprovedSimple[T constraints.Ordered](arr []T) []T { for i := 1; i < len(arr); i++ { for j := 0; j < len(arr)-1; j++ { if arr[i] < arr[j] { diff --git a/sort/sorts_test.go b/sort/sorts_test.go index 828b907cb..08b6a716d 100644 --- a/sort/sorts_test.go +++ b/sort/sorts_test.go @@ -1,6 +1,7 @@ -package sort +package sort_test import ( + "github.com/TheAlgorithms/Go/sort" "reflect" "testing" ) @@ -75,63 +76,63 @@ func testFramework(t *testing.T, sortingFunction func([]int) []int) { //BEGIN TESTS func TestBubble(t *testing.T) { - testFramework(t, bubbleSort) + testFramework(t, sort.Bubble[int]) } func TestExchange(t *testing.T) { - testFramework(t, Exchange) + testFramework(t, sort.Exchange[int]) } func TestInsertion(t *testing.T) { - testFramework(t, InsertionSort) + testFramework(t, sort.Insertion[int]) } func TestMerge(t *testing.T) { - testFramework(t, Mergesort) + testFramework(t, sort.Merge[int]) } func TestMergeIter(t *testing.T) { - testFramework(t, MergeIter) + testFramework(t, sort.MergeIter[int]) } func TestHeap(t *testing.T) { - testFramework(t, HeapSort) + testFramework(t, sort.HeapSort) } func TestCount(t *testing.T) { - testFramework(t, Count) + testFramework(t, sort.Count[int]) } func TestQuick(t *testing.T) { - testFramework(t, QuickSort) + testFramework(t, sort.Quicksort[int]) } func TestShell(t *testing.T) { - testFramework(t, ShellSort) + testFramework(t, sort.Shell[int]) } func TestRadix(t *testing.T) { - testFramework(t, RadixSort) + testFramework(t, sort.RadixSort) } func TestSimple(t *testing.T) { - testFramework(t, SimpleSort) + testFramework(t, sort.Simple[int]) } func TestImprovedSimple(t *testing.T) { - testFramework(t, ImprovedSimpleSort) + testFramework(t, sort.ImprovedSimple[int]) } func TestSelection(t *testing.T) { - testFramework(t, SelectionSort) + testFramework(t, sort.Selection[int]) } func TestComb(t *testing.T) { - testFramework(t, Comb) + testFramework(t, sort.Comb[int]) } func TestPigeonhole(t *testing.T) { - testFramework(t, Pigeonhole) + testFramework(t, sort.Pigeonhole) } //END TESTS @@ -176,62 +177,62 @@ func benchmarkFramework(b *testing.B, f func(arr []int) []int) { //BEGIN BENCHMARKS func BenchmarkBubble(b *testing.B) { - benchmarkFramework(b, bubbleSort) + benchmarkFramework(b, sort.Bubble[int]) } func BenchmarkExchange(b *testing.B) { - benchmarkFramework(b, Exchange) + benchmarkFramework(b, sort.Exchange[int]) } func BenchmarkInsertion(b *testing.B) { - benchmarkFramework(b, InsertionSort) + benchmarkFramework(b, sort.Insertion[int]) } func BenchmarkMerge(b *testing.B) { - benchmarkFramework(b, Mergesort) + benchmarkFramework(b, sort.Merge[int]) } func BenchmarkMergeIter(b *testing.B) { - benchmarkFramework(b, MergeIter) + benchmarkFramework(b, sort.MergeIter[int]) } func BenchmarkHeap(b *testing.B) { - benchmarkFramework(b, HeapSort) + benchmarkFramework(b, sort.HeapSort) } func BenchmarkCount(b *testing.B) { - benchmarkFramework(b, Count) + benchmarkFramework(b, sort.Count[int]) } func BenchmarkQuick(b *testing.B) { - benchmarkFramework(b, QuickSort) + benchmarkFramework(b, sort.Quicksort[int]) } func BenchmarkShell(b *testing.B) { - benchmarkFramework(b, ShellSort) + benchmarkFramework(b, sort.Shell[int]) } func BenchmarkRadix(b *testing.B) { - benchmarkFramework(b, RadixSort) + benchmarkFramework(b, sort.RadixSort) } func BenchmarkSimple(b *testing.B) { - benchmarkFramework(b, SimpleSort) + benchmarkFramework(b, sort.Simple[int]) } func BenchmarkImprovedSimple(b *testing.B) { - benchmarkFramework(b, ImprovedSimpleSort) + benchmarkFramework(b, sort.ImprovedSimple[int]) } // Very Slow, consider commenting func BenchmarkSelection(b *testing.B) { - benchmarkFramework(b, SelectionSort) + benchmarkFramework(b, sort.Selection[int]) } func BenchmarkComb(b *testing.B) { - benchmarkFramework(b, Comb) + benchmarkFramework(b, sort.Comb[int]) } func BenchmarkPigeonhole(b *testing.B) { - benchmarkFramework(b, Pigeonhole) + benchmarkFramework(b, sort.Pigeonhole) }