summaryrefslogtreecommitdiff
path: root/gemfeed/2023-04-09-algorithms-in-golang-part-1.gmi
diff options
context:
space:
mode:
Diffstat (limited to 'gemfeed/2023-04-09-algorithms-in-golang-part-1.gmi')
-rw-r--r--gemfeed/2023-04-09-algorithms-in-golang-part-1.gmi229
1 files changed, 229 insertions, 0 deletions
diff --git a/gemfeed/2023-04-09-algorithms-in-golang-part-1.gmi b/gemfeed/2023-04-09-algorithms-in-golang-part-1.gmi
new file mode 100644
index 00000000..2ac5faa8
--- /dev/null
+++ b/gemfeed/2023-04-09-algorithms-in-golang-part-1.gmi
@@ -0,0 +1,229 @@
+# Algorithms in Go - Part 1
+
+> Published at 2023-04-09T21:48:36+03:00
+
+```
+ ,_---~~~~~----._
+ _,,_,*^____ _____``*g*\"*,
+ / __/ /' ^. / \ ^@q f
+[ @f | @)) | | @)) l 0 _/
+ \`/ \~____ / __ \_____/ \
+ | _l__l_ I
+ } [______] I
+ ] | | | |
+ ] ~ ~ |
+ | |
+ | |
+```
+
+This is the first blog post about my Algorithms in Go series. I am not a Software Developer in my day job. In my current role, programming and scripting skills are desirable but not mandatory. I have been learning about Data Structures and Algorithms many years ago at University. I thought it would be fun to revisit/refresh my knowledge here and implement many of the algorithms in Go.
+
+=> ./2023-04-09-algorithms-in-golang-part-1.gmi 2023-04-09 Algorithms in Go - Part 1 (You are currently reading this)
+
+This post is about setting up some basic data structures and methods for this blog series. I promise, everything will be easy to follow in this post.
+
+## Type constraints
+
+First, the package `ds` (data structures) defines the `types.go`. All examples will either operate on the `Integer` or `Number` type:
+
+```go
+package ds
+
+import (
+ "golang.org/x/exp/constraints"
+)
+
+type Integer interface {
+ constraints.Integer
+}
+
+type Number interface {
+ constraints.Integer | constraints.Float
+}
+
+```
+
+## ArrayList
+
+Next comes the `arraylist.go`, which defines the underlying data structure all the algorithms of this series will use. `ArrayList` is just a type alias of a Go array (or slice) with custom methods on it:
+
+```go
+package ds
+
+import (
+ "fmt"
+ "math/rand"
+ "strings"
+)
+
+type ArrayList[V Number] []V
+
+func NewArrayList[V Number](l int) ArrayList[V] {
+ return make(ArrayList[V], l)
+}
+```
+
+As you can see, the code uses Go generics, which I refactored recently. Besides the default constructor (which only returns an empty `ArrayList` with a given capacity), there are also a bunch of special constructors. `NewRandomArrayList` is returning an `ArrayList` with random numbers, `NewAscendingArrayList` and `NewDescendingArrayList` are returning `ArrayList`s in either ascending or descending order. They all will be used later on for testing and benchmarking the algorithms.
+
+```go
+func NewRandomArrayList[V Number](l, max int) ArrayList[V] {
+ a := make(ArrayList[V], l)
+ for i := 0; i < l; i++ {
+ if max > 0 {
+ a[i] = V(rand.Intn(max))
+ continue
+ }
+ a[i] = V(rand.Int())
+ }
+ return a
+}
+
+func NewAscendingArrayList[V Number](l int) ArrayList[V] {
+ a := make(ArrayList[V], l)
+ for i := 0; i < l; i++ {
+ a[i] = V(i)
+ }
+ return a
+}
+
+func NewDescendingArrayList[V Number](l int) ArrayList[V] {
+ a := make(ArrayList[V], l)
+ j := l - 1
+ for i := 0; i < l; i++ {
+ a[i] = V(j)
+ j--
+ }
+ return a
+}
+```
+
+## Helper methods
+
+The `FirstN` method only returns the first N elements of the `ArrayList`. This is useful for printing out only parts of the data structure:
+
+```go
+func (a ArrayList[V]) FirstN(n int) string {
+ var sb strings.Builder
+ j := n
+
+ l := len(a)
+ if j > l {
+ j = l
+ }
+
+ for i := 0; i < j; i++ {
+ fmt.Fprintf(&sb, "%v ", a[i])
+ }
+
+ if j < l {
+ fmt.Fprintf(&sb, "... ")
+ }
+
+ return sb.String()
+}
+```
+
+The `Sorted` method checks whether the `ArrayList` is sorted. This will be used by the unit tests later on:
+
+```go
+func (a ArrayList[V]) Sorted() bool {
+ for i := len(a) - 1; i > 0; i-- {
+ if a[i] < a[i-1] {
+ return false
+ }
+ }
+ return true
+}
+```
+
+And the last utility method used is `Swap`, which allows swapping the values of two indices in the `ArrayList`:
+
+```go
+func (a ArrayList[V]) Swap(i, j int) {
+ aux := a[i]
+ a[i] = a[j]
+ a[j] = aux
+}
+
+```
+
+## Sleep sort
+
+Let's implement our first algorithm, sleep sort. Sleep sort is a non-traditional and unconventional sorting algorithm based on the idea of waiting a certain amount of time corresponding to the value of each element in the input `ArrayList`. It's more of a fun, creative concept rather than an efficient or practical sorting technique. This is not a sorting algorithm you would use in any production code. As you can imagine, it is quite an inefficient sorting algorithm (it's only listed here as a warm-up exercise). This sorting method may also return false results depending on how the Goroutines are scheduled by the Go runtime.
+
+
+```go
+package sort
+
+import (
+ "codeberg.org/snonux/algorithms/ds"
+ "sync"
+ "time"
+)
+
+func Sleep[V ds.Integer](a ds.ArrayList[V]) ds.ArrayList[V] {
+ sorted := ds.NewArrayList[V](len(a))
+
+ numCh := make(chan V)
+ var wg sync.WaitGroup
+ wg.Add(len(a))
+
+ go func() {
+ wg.Wait()
+ close(numCh)
+ }()
+
+ for _, num := range a {
+ go func(num V) {
+ defer wg.Done()
+ time.Sleep(time.Duration(num) * time.Second)
+ numCh <- num
+ }(num)
+ }
+
+ for num := range numCh {
+ sorted = append(sorted, num)
+ }
+
+ return sorted
+}
+```
+
+### Testing
+
+For testing, we only allow values up to 10, as otherwise, it would take too long to finish:
+
+```go
+package sort
+
+import (
+ "fmt"
+ "testing"
+
+ "codeberg.org/snonux/algorithms/ds"
+)
+
+func TestSleepSort(t *testing.T) {
+ a := ds.NewRandomArrayList[int](10, 10)
+ a = Sleep(a)
+ if !a.Sorted() {
+ t.Errorf("Array not sorted: %v", a)
+ }
+}
+```
+
+As you can see, it takes `9s` here for the algorithm to finish (which is the highest value in the `ArrayList`):
+
+```sh
+❯ go test ./sort -v -run SleepSort
+=== RUN TestSleepSort
+--- PASS: TestSleepSort (9.00s)
+PASS
+ok codeberg.org/snonux/algorithms/sort 9.002s
+```
+
+I won't write any benchmark for sleep sort; that will be done for the algorithms to come in this series :-).
+
+E-Mail your comments to hi@paul.cyou :-)
+
+=> ../ Back to the main site