'How to shuffle strings in arrays in golang?

So I created a program to help me decide which game to play. Before I start my problem let me show you my code:

package main

import (
    "fmt"
    "strconv"
    "time"
)

func main() {
    isArray := [10]string{"Paladins", "Overwatch", "CS:GO", "Tanki", "Left 4 Dead", "Rocket League", "Call Of Duty : AW", "Portal", "Star Citizen", "Star Wars : Battlefront"}
    fmt.Print("0,1,2,3,4,5,6,7,8,9 := ")

    var (
        va string
        ar string
    )

    fmt.Scanln(&va)
    i, _ := strconv.Atoi(va)

    fmt.Print("You Should Play : ")
    fmt.Print(isArray[i], "\n")
    fmt.Print("[Y/N] := ")
    fmt.Scanln(&ar)

    if ar != "N" || ar != "n" {
        fmt.Print("OK")
    }

    time.Sleep(3 * time.Second)
}

So the problems start when I already know which number would trigger a game, if I use it twice. So I am trying to make the strings random, like shuffling each time I use it, how can I do that?



Solution 1:[1]

Well, literally for your problem why not use rand.Intn() to choose a random number and print the game rather than make the user pick a number?

isArray := [10]string{"Paladins", "Overwatch", "CS:GO", "Tanki", "Left 4 Dead", "Rocket League", "Call Of Duty : AW", "Portal", "Star Citizen", "Star Wars : Battlefront"}
n := rand.Intn(9)
fmt.Printf("You Should Play : %s\n", isArray[n])

But if you want to shuffle strings in an array for the sake of it, then you can do it in place like this:

// Shuffle array in place
l := len(isArray)-1
for i := 0; i <=l; i++ {
    n := rand.Intn(l)
    // swap
    x := isArray[i]
    isArray[i] = isArray[n]
    isArray[n] = x
}

This should be O(n), though I'm not sure about the complexity of Intn. If you really want to be fancy, you could:

  1. Create a second array (randomArray) of touples, containing a random number and element position in isArray.
  2. Sort this array by the random number
  3. Create a new array, copying elements of isArray, but ordered by our randomArray

Solution 2:[2]

 package main

 import (
         "fmt"
         "math/rand"
         "time"
 )

 func shuffle(src []string) []string {
         final := make([]string, len(src))
         rand.Seed(time.Now().UTC().UnixNano())
         perm := rand.Perm(len(src))

         for i, v := range perm {
                 final[v] = src[i]
         }
         return final
 }

Solution 3:[3]

package main

import (
    "fmt"
    "math/rand"
    "time"
)

type list []string

func main() {

    s := list{
        "Tanki",
        "Left 4 Dead",
        "Rocket League",
        "Call Of Duty : AW",
    }
    s.shuffle()
    s.print()
}

func (l list) print() {
    for i, v := range l {
        fmt.Println(i, v)
    }
}

func (l list) shuffle() list {
    src := rand.NewSource(time.Now().UnixNano())
    r := rand.New(src)
    for i := range l {
        n := r.Intn(len(l) - 1)
        l[i], l[n] = l[n], l[i]
    }
    return l
}

Solution 4:[4]

You can now use the rand.Shuffle function from the math package.

    var games = [10]string{"Paladins", "Overwatch", "CS:GO", "Tanki", "Left 4 Dead", "Rocket League", "Call Of Duty : AW", "Portal", "Star Citizen", "Star Wars : Battlefront"}

    rand.Seed(time.Now().UnixNano())
    rand.Shuffle(len(games), func(i, j int) {
        games[i], games[j] = games[j], games[i]
    })

    fmt.Println(games)

docs: https://pkg.go.dev/math/rand#Shuffle

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 abdel
Solution 3 Sathish Kumar Pothuri
Solution 4 leonardo