├── .gitignore ├── LICENSE ├── README.md ├── bubble_sort.go ├── cocktail_shaker_sort.go ├── comb_sort.go ├── gnome_sort.go ├── go.mod ├── go.sum ├── insertion_sort.go ├── main.go ├── odd_even_sort.go ├── selection_sort.go ├── sorting_algorithms.go └── utils.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | cli-algorithms-visualizer -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 go-nerds 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cli-algorithms-visualizer 2 | 3 | ## Introduction 4 | 5 | This project is an algorithms visualizer implemented in Go. It allows you to observe various algorithms in action. The visualizer provides a graphical representation of each step, making it easier to understand how the algorithms work. 6 | 7 | ## How to Use 8 | 9 | 1. Clone the repository to your local machine: 10 | 11 | ```bash 12 | git clone https://github.com/go-nerds/cli-algorithms-visualizer.git 13 | ``` 14 | 15 | 2. Build the project: 16 | ```bash 17 | go build 18 | ``` 19 | 3. Run the executable file: 20 | ```bash 21 | .\.exe // Windows OS 22 | ./ // Linux || Mac OS 23 | ``` 24 | ## LICENSE 25 | 26 | This project is licensed under the MIT License. See the [LICENSE](https://github.com/go-nerds/cli-algorithms-visualizer/blob/main/LICENSE) file for details. 27 | -------------------------------------------------------------------------------- /bubble_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | func bubbleSortVisualizer(arr []int, delay time.Duration) { 6 | n := len(arr) 7 | for i := 0; i < n-1; i++ { 8 | for j := 0; j < n-i-1; j++ { 9 | visualizeIteration(arr, j, j+1, delay) 10 | if arr[j] > arr[j+1] { 11 | visualizeIteration(arr, j, j+1, delay) 12 | arr[j], arr[j+1] = arr[j+1], arr[j] 13 | visualizeIteration(arr, j, j+1, delay) 14 | } 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /cocktail_shaker_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | func cocktailShakerSortVisualizer(arr []int, delay time.Duration) { 6 | left := 0 7 | right := len(arr) - 1 8 | 9 | for left <= right { 10 | for i := left; i < right; i++ { 11 | visualizeIteration(arr, i, i+1, delay) 12 | if arr[i] > arr[i+1] { 13 | visualizeIteration(arr, i, i+1, delay) 14 | arr[i], arr[i+1] = arr[i+1], arr[i] 15 | visualizeIteration(arr, i, i+1, delay) 16 | } 17 | } 18 | right-- 19 | 20 | for i := right; i > left; i-- { 21 | visualizeIteration(arr, i-1, i, delay) 22 | if arr[i-1] > arr[i] { 23 | visualizeIteration(arr, i-1, i, delay) 24 | arr[i], arr[i-1] = arr[i-1], arr[i] 25 | visualizeIteration(arr, i-1, i, delay) 26 | } 27 | } 28 | left++ 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /comb_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | func combSortVisualizer(arr []int, delay time.Duration) { 6 | n := len(arr) 7 | gap := n 8 | swapped := true 9 | 10 | for gap > 1 || swapped { 11 | gap = getNextGap(gap) 12 | swapped = false 13 | 14 | for i := 0; i < n-gap; i++ { 15 | visualizeIteration(arr, i, i+gap, delay) 16 | if arr[i] > arr[i+gap] { 17 | visualizeIteration(arr, i, i+gap, delay) 18 | arr[i], arr[i+gap] = arr[i+gap], arr[i] 19 | visualizeIteration(arr, i, i+gap, delay) 20 | swapped = true 21 | } 22 | } 23 | } 24 | } 25 | 26 | func getNextGap(gap int) int { 27 | gap = (gap * 10) / 13 28 | if gap < 1 { 29 | return 1 30 | } 31 | return gap 32 | } 33 | -------------------------------------------------------------------------------- /gnome_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | func gnomeSortVisualizer(arr []int, delay time.Duration) { 6 | i := 1 7 | 8 | for i < len(arr) { 9 | if i == 0 || arr[i] >= arr[i-1] { 10 | visualizeIteration(arr, i-1, i, delay) 11 | i++ 12 | } else { 13 | visualizeIteration(arr, i-1, i, delay) 14 | arr[i], arr[i-1] = arr[i-1], arr[i] 15 | visualizeIteration(arr, i-1, i, delay) 16 | i-- 17 | if i == 0 { 18 | i = 1 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/go-nerds/cli-algorithms-visualizer 2 | 3 | go 1.20 4 | 5 | require ( 6 | atomicgo.dev/cursor v0.1.3 // indirect 7 | atomicgo.dev/keyboard v0.2.9 // indirect 8 | atomicgo.dev/schedule v0.0.2 // indirect 9 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect 10 | github.com/containerd/console v1.0.3 // indirect 11 | github.com/gookit/color v1.5.3 // indirect 12 | github.com/lithammer/fuzzysearch v1.1.8 // indirect 13 | github.com/manifoldco/promptui v0.9.0 // indirect 14 | github.com/mattn/go-runewidth v0.0.14 // indirect 15 | github.com/pterm/pterm v0.12.63 // indirect 16 | github.com/rivo/uniseg v0.4.4 // indirect 17 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect 18 | golang.org/x/sys v0.10.0 // indirect 19 | golang.org/x/term v0.10.0 // indirect 20 | golang.org/x/text v0.11.0 // indirect 21 | ) 22 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | atomicgo.dev/cursor v0.1.3 h1:w8GcylMdZRyFzvDiGm3wy3fhZYYT7BwaqNjUFHxo0NU= 2 | atomicgo.dev/cursor v0.1.3/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= 3 | atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= 4 | atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= 5 | atomicgo.dev/schedule v0.0.2 h1:2e/4KY6t3wokja01Cyty6qgkQM8MotJzjtqCH70oX2Q= 6 | atomicgo.dev/schedule v0.0.2/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= 7 | github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= 8 | github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= 9 | github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= 10 | github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= 11 | github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= 12 | github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= 13 | github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= 14 | github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= 15 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 16 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8= 17 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 18 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 19 | github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= 20 | github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= 21 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 22 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 23 | github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= 24 | github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= 25 | github.com/gookit/color v1.5.3 h1:twfIhZs4QLCtimkP7MOxlF3A0U/5cDPseRT9M/+2SCE= 26 | github.com/gookit/color v1.5.3/go.mod h1:NUzwzeehUfl7GIb36pqId+UGmRfQcU/WiiyTTeNjHtE= 27 | github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= 28 | github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= 29 | github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= 30 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 31 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 32 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 33 | github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= 34 | github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= 35 | github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= 36 | github.com/manifoldco/promptui v0.9.0/go.mod h1:ka04sppxSGFAtxX0qhlYQjISsg9mR4GWtQEhdbn6Pgg= 37 | github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 38 | github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= 39 | github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 40 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 41 | github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= 42 | github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= 43 | github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= 44 | github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= 45 | github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= 46 | github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= 47 | github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= 48 | github.com/pterm/pterm v0.12.63 h1:fHlrpFiI9qLtEU0TWDWMU+tAt4qKJ/s157BEAPtGm8w= 49 | github.com/pterm/pterm v0.12.63/go.mod h1:Bq1eoUJ6BhUzzXG8WxA4l7T3s7d3Ogwg7v9VXlsVat0= 50 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 51 | github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= 52 | github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 53 | github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 54 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 55 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 56 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 57 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 58 | github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= 59 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= 60 | github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= 61 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 62 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 63 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 64 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 65 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 66 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 67 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 68 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 69 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 70 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 71 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 72 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 73 | golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 74 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 75 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 76 | golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 77 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 78 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 79 | golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 80 | golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 81 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 82 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 83 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 84 | golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= 85 | golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 86 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 87 | golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 88 | golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 89 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 90 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 91 | golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= 92 | golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= 93 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 94 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 95 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 96 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 97 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 98 | golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= 99 | golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 100 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 101 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 102 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 103 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 104 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 105 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 106 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 107 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 108 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 109 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 110 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 111 | -------------------------------------------------------------------------------- /insertion_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | func insertionSortVisualizer(arr []int, delay time.Duration) { 8 | for i := 1; i < len(arr); i++ { 9 | j := i 10 | visualizeIteration(arr, j-1, j, delay) 11 | for j > 0 && arr[j] < arr[j-1] { 12 | visualizeIteration(arr, j-1, j, delay) 13 | arr[j], arr[j-1] = arr[j-1], arr[j] 14 | visualizeIteration(arr, j-1, j, delay) 15 | j-- 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "os" 7 | "strings" 8 | "time" 9 | 10 | "github.com/manifoldco/promptui" 11 | ) 12 | 13 | type options struct { 14 | Name SortingAlgorithm 15 | } 16 | 17 | func main() { 18 | clearConsole() 19 | 20 | r := bufio.NewReader(os.Stdin) 21 | n := getSliceSize(r) 22 | arr := make([]int, 0, n) 23 | fillSliceWithRandElems(&arr) 24 | 25 | fmt.Println("Initial array:", arr) 26 | 27 | algorithms := []options{ 28 | {Name: BubbleSort}, 29 | {Name: SelectionSort}, 30 | {Name: InsertionSort}, 31 | {Name: GnomeSort}, 32 | {Name: CocktailShakerSort}, 33 | {Name: CombSort}, 34 | {Name: OddEvenSort}, 35 | } 36 | 37 | templates := &promptui.SelectTemplates{ 38 | Label: "{{ . }}?", 39 | Active: "--> {{ .Name | cyan }}", 40 | Inactive: " {{ .Name | cyan }}", 41 | Selected: "--> {{ .Name | cyan }}", 42 | Details: ` 43 | --------- Algorithm ---------- 44 | {{ "Name:" | faint }} {{ .Name }} 45 | `, 46 | } 47 | 48 | searcher := func(input string, index int) bool { 49 | algorithm := algorithms[index] 50 | name := strings.Replace(strings.ToLower(algorithm.Name.String()), " ", "", -1) 51 | input = strings.Replace(strings.ToLower(input), " ", "", -1) 52 | 53 | return strings.Contains(name, input) 54 | } 55 | 56 | algorithmPrompt := promptui.Select{ 57 | Label: "Select a sorting algorithm!", 58 | Items: algorithms, 59 | Templates: templates, 60 | Size: 4, 61 | Searcher: searcher, 62 | } 63 | 64 | i, _, err := algorithmPrompt.Run() 65 | 66 | if err != nil { 67 | fmt.Printf("Prompt failed: %s\n", err.Error()) 68 | return 69 | } 70 | 71 | clearConsole() 72 | 73 | actionPrompt := promptui.Select{ 74 | Label: "Select Action", 75 | Items: []string{"Description", "Run"}, 76 | } 77 | 78 | _, action, err := actionPrompt.Run() 79 | if err != nil { 80 | fmt.Printf("Prompt failed %v\n", err) 81 | return 82 | } 83 | 84 | clearConsole() 85 | 86 | switch action { 87 | case "Description": 88 | printAlgorithmDescription(algorithms[i].Name) 89 | case "Run": 90 | speedPrompt := promptui.Select{ 91 | Label: "Select Visualization Speed", 92 | Items: []string{"Slow", "Medium", "Fast", "Very Fast"}, 93 | } 94 | 95 | _, speed, err := speedPrompt.Run() 96 | if err != nil { 97 | fmt.Printf("Prompt failed %v\n", err) 98 | return 99 | } 100 | 101 | var delay time.Duration 102 | switch speed { 103 | case "Slow": 104 | delay = time.Millisecond * 1500 105 | case "Medium": 106 | delay = time.Second 107 | case "Fast": 108 | delay = time.Second / 2 109 | case "Very Fast": 110 | delay = time.Second / 4 111 | default: 112 | delay = time.Second 113 | } 114 | 115 | clearConsole() 116 | runAlgorithm(algorithms[i].Name, arr, delay) 117 | default: 118 | fmt.Println("Invalid choice") 119 | return 120 | } 121 | } 122 | 123 | func runAlgorithm(algorithm SortingAlgorithm, arr []int, delay time.Duration) { 124 | switch algorithm { 125 | case BubbleSort: 126 | bubbleSortVisualizer(arr, delay) 127 | case SelectionSort: 128 | selectionSortVisualizer(arr, delay) 129 | case InsertionSort: 130 | insertionSortVisualizer(arr, delay) 131 | case GnomeSort: 132 | gnomeSortVisualizer(arr, delay) 133 | case CocktailShakerSort: 134 | cocktailShakerSortVisualizer(arr, delay) 135 | case CombSort: 136 | combSortVisualizer(arr, delay) 137 | case OddEvenSort: 138 | oddEvenSortVisualizer(arr, delay) 139 | default: 140 | fmt.Println("Invalid selection") 141 | } 142 | fmt.Println("Sorted array:", arr) 143 | } 144 | -------------------------------------------------------------------------------- /odd_even_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "time" 4 | 5 | func oddEvenSortVisualizer(arr []int, delay time.Duration) { 6 | n := len(arr) 7 | sorted := false 8 | 9 | for !sorted { 10 | sorted = true 11 | for i := 1; i <= n-2; i += 2 { 12 | visualizeIteration(arr, i, i+1, delay) 13 | if arr[i] > arr[i+1] { 14 | visualizeIteration(arr, i, i+1, delay) 15 | arr[i], arr[i+1] = arr[i+1], arr[i] 16 | visualizeIteration(arr, i, i+1, delay) 17 | sorted = false 18 | } 19 | } 20 | 21 | for i := 0; i <= n-2; i += 2 { 22 | visualizeIteration(arr, i, i+1, delay) 23 | if arr[i] > arr[i+1] { 24 | visualizeIteration(arr, i, i+1, delay) 25 | arr[i], arr[i+1] = arr[i+1], arr[i] 26 | visualizeIteration(arr, i, i+1, delay) 27 | sorted = false 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /selection_sort.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | func selectionSortVisualizer(arr []int, delay time.Duration) { 8 | for i := 0; i < len(arr); i++ { 9 | min := i 10 | for j := i + 1; j < len(arr); j++ { 11 | visualizeIteration(arr, i, j, delay) 12 | if arr[j] < arr[min] { 13 | visualizeIteration(arr, i, j, delay) 14 | min = j 15 | } 16 | } 17 | arr[i], arr[min] = arr[min], arr[i] 18 | visualizeIteration(arr, i, min, delay) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /sorting_algorithms.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | type SortingAlgorithm uint8 4 | 5 | const ( 6 | BubbleSort SortingAlgorithm = iota 7 | SelectionSort 8 | InsertionSort 9 | GnomeSort 10 | CocktailShakerSort 11 | CombSort 12 | OddEvenSort 13 | ) 14 | 15 | func (a SortingAlgorithm) String() string { 16 | switch a { 17 | case BubbleSort: 18 | return "Bubble Sort" 19 | case SelectionSort: 20 | return "Selection Sort" 21 | case InsertionSort: 22 | return "Insertion Sort" 23 | case GnomeSort: 24 | return "Gnome Sort" 25 | case CocktailShakerSort: 26 | return "Cocktail Shaker Sort" 27 | case CombSort: 28 | return "Comb Sort" 29 | case OddEvenSort: 30 | return "Odd-Even Sort" 31 | default: 32 | return "Invalid selection" 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bufio" 5 | "fmt" 6 | "math/rand" 7 | "os" 8 | "os/exec" 9 | "runtime" 10 | "strconv" 11 | "strings" 12 | "time" 13 | 14 | "github.com/gookit/color" 15 | ) 16 | 17 | type Color int 18 | 19 | func clearConsole() { 20 | switch runtime.GOOS { 21 | case "linux", "darwin": 22 | cmd := exec.Command("clear") 23 | cmd.Stdout = os.Stdout 24 | cmd.Run() 25 | case "windows": 26 | cmd := exec.Command("cmd", "/c", "cls") 27 | cmd.Stdout = os.Stdout 28 | cmd.Run() 29 | default: 30 | fmt.Println("Unsupported platform. Cannot clear console.") 31 | } 32 | } 33 | 34 | func printColoredArray(array []int, idx1, idx2 int) { 35 | fmt.Print("[") 36 | for i := range array { 37 | if idx1 == i { 38 | fmt.Print(color.OpUnderscore.Sprint(color.LightYellow.Sprint(array[idx1]), " ")) 39 | } else if idx2 == i { 40 | fmt.Print(color.OpUnderscore.Sprint(color.LightYellow.Sprint(array[idx2]), " ")) 41 | } else { 42 | fmt.Print(array[i], " ") 43 | } 44 | } 45 | fmt.Println("]") 46 | fmt.Println() 47 | 48 | } 49 | 50 | func visualizeIteration(array []int, idx1 int, idx2 int, delay time.Duration) { 51 | printColoredArray(array, idx1, idx2) 52 | time.Sleep(delay) 53 | clearConsole() 54 | } 55 | 56 | func printAlgorithmDescription(algorithm SortingAlgorithm) { 57 | switch algorithm { 58 | case BubbleSort: 59 | color.Bold.Println(color.Yellow.Sprint("Bubble Sort")) 60 | fmt.Println() 61 | fmt.Println(color.Cyan.Sprint("Bubble Sort is a simple comparison-based sorting algorithm. It works by repeatedly stepping through the list to be sorted,")) 62 | fmt.Println(color.Cyan.Sprint("compares adjacent elements, and swaps them if they are in the wrong order. The pass through the list is repeated until the list")) 63 | fmt.Println(color.Cyan.Sprint("is sorted. The algorithm gets its name from the way smaller elements 'bubble' to the top of the list.")) 64 | case SelectionSort: 65 | color.Bold.Println(color.Yellow.Sprint("Selection Sort")) 66 | fmt.Println() 67 | fmt.Println(color.Cyan.Sprint("Selection Sort is an in-place comparison-based sorting algorithm. It works by dividing the input list into two parts:")) 68 | fmt.Println(color.Cyan.Sprint("the sorted part and the unsorted part. The algorithm repeatedly selects the minimum element from the unsorted part")) 69 | fmt.Println(color.Cyan.Sprint("and moves it to the end of the sorted part. This process continues until the entire list is sorted.")) 70 | case InsertionSort: 71 | color.Bold.Println(color.Yellow.Sprint("Insertion Sort")) 72 | fmt.Println() 73 | fmt.Println(color.Cyan.Sprint("Insertion Sort is an in-place comparison-based sorting algorithm. It works by dividing the input list into two parts:")) 74 | fmt.Println(color.Cyan.Sprint("the sorted part and the unsorted part. The algorithm repeatedly picks an element from the unsorted part and inserts")) 75 | fmt.Println(color.Cyan.Sprint("it into the correct position in the sorted part. This process continues until the entire list is sorted.")) 76 | case GnomeSort: 77 | color.Bold.Println(color.Yellow.Sprint("Gnome Sort")) 78 | fmt.Println() 79 | fmt.Println(color.Cyan.Sprint("Gnome Sort is an in-place comparison-based sorting algorithm. It works by repeatedly comparing adjacent elements.")) 80 | fmt.Println(color.Cyan.Sprint("If the two elements are in the wrong order, it swaps them and moves one step backward. If the two elements")) 81 | fmt.Println(color.Cyan.Sprint("are in the correct order, it moves one step forward. This process continues until the entire list is sorted.")) 82 | case CocktailShakerSort: 83 | color.Bold.Println(color.Yellow.Sprint("Cocktail Shaker Sort")) 84 | fmt.Println() 85 | fmt.Println(color.Cyan.Sprint("Cocktail Shaker Sort, also known as Bidirectional Bubble Sort, is a variation of Bubble Sort. It works by repeatedly")) 86 | fmt.Println(color.Cyan.Sprint("sorting the list in both directions, first from the beginning to the end (like Bubble Sort), and then from the end")) 87 | fmt.Println(color.Cyan.Sprint("to the beginning. The algorithm stops when the list becomes sorted.")) 88 | case CombSort: 89 | color.Bold.Println(color.Yellow.Sprint("Comb Sort")) 90 | fmt.Println() 91 | fmt.Println(color.Cyan.Sprint("Comb Sort is an in-place comparison-based sorting algorithm. It works by dividing the input list into a series of")) 92 | fmt.Println(color.Cyan.Sprint("gaps and repeatedly sorting the list with a specific shrink factor. The shrink factor reduces the gaps until it becomes 1.")) 93 | fmt.Println(color.Cyan.Sprint("At this point, the algorithm behaves similar to Bubble Sort. Comb Sort is an improvement over Bubble Sort for large lists.")) 94 | case OddEvenSort: 95 | color.Bold.Println(color.Yellow.Sprint("Odd-Even Sort")) 96 | fmt.Println() 97 | fmt.Println(color.Cyan.Sprint("Odd-Even Sort is an in-place comparison-based sorting algorithm. It works by repeatedly comparing and swapping")) 98 | fmt.Println(color.Cyan.Sprint("adjacent elements at even and odd indices. The process continues until the list is sorted. Odd-Even Sort is known")) 99 | fmt.Println(color.Cyan.Sprint("for its simplicity but is not very efficient for large lists.")) 100 | default: 101 | fmt.Println("Invalid selection") 102 | } 103 | } 104 | 105 | func getSliceSize(r *bufio.Reader) int { 106 | var n int 107 | for { 108 | fmt.Print("Enter the size of the: ") 109 | str, err := r.ReadString('\n') 110 | if err != nil { 111 | fmt.Println("Error reading input: ", err) 112 | continue 113 | } 114 | n, err = strconv.Atoi(strings.Trim(str, "\n")) 115 | if err != nil { 116 | fmt.Println("Input must be a number") 117 | continue 118 | } 119 | break 120 | } 121 | return n 122 | } 123 | 124 | func fillSliceWithRandElems(s *[]int) { 125 | for i := 0; i < cap(*s); i++ { 126 | *s = append(*s, rand.Intn(cap(*s)*10)) 127 | } 128 | } 129 | --------------------------------------------------------------------------------