1

I'm dealing with go/golang, trying to write code that takes a string and seed. It should return a shuffled string where the 1st and last letters in the word, punctuation and numbers are untouched.

Example:

my name is Nikki. My number is 333

should be

my nmae is Nkiki. My nebumr is 333

I'm very new to goland/go. Have tried to do it with rand.Shuffle:

   func splitText(text string) []string {
    re := regexp.MustCompile("[A-Za-z0-9']+|[':;?().,!\\ ]")
    return re.FindAllString(text, -1)}


    func scramble(text string, seed int64) string {

    rand.Seed(seed)
    split := splitText(text)

    for i := range split {
        e := split[i]

        r := []byte(e)

        for i := 0; i < len(r); i++ {
            l := len(r) - 1
            if i == 0 {
                return string(r[0])
            }
            if i == l {
                return string(r[l])
            }

            if i > 0 || i < l {
                n := rand.Intn(l)
                x := r[i]
                r[i] = r[n]
                r[n] = x

            }

            if (r[i] >= 32 && r[i] <= 62) || (r[i] >= 91 && r[i] <= 96) {
                return string(r[i])
            }
        }

    }
    return text

}

func main() {

    v := ("The quick brown fox jumps over the lazy dog.")
    scramble(v, 100)
    fmt.Println(scramble(v, 100))

}

But this returns only one letter and only if remoe f==0 or f==l, it doesn't hop to the next word.

Cindy Meister
  • 25,071
  • 21
  • 34
  • 43
  • In the nested for-loop, you have an `if i==0` condition, which is always true the first time that loop runs, so it returns without executing the rest of the code. Inner for-loop index `i` is shadowing the outer loop `i`, so maybe that's the source of your confusion. – Burak Serdar Sep 15 '19 at 18:04
  • but how to fix so that i it will print and shuffle? –  Sep 15 '19 at 18:11
  • 1
    With the way you're doing it, you'll lose word boundaries and punctuation. So I suggest you change your algorithm. One way you can do this is to convert your string to a []rune, and iterate the elements. As you're iterating, find out word boundaries, shuffle the bytes in between using rand.Shuffle, and convert the resulting []rune to string and return. – Burak Serdar Sep 15 '19 at 18:41
  • can you explain with some code example? –  Sep 15 '19 at 18:52
  • 1
    I can't write the code for you, but the algorithm I described need to keep a state variable that tells whether you're in a word or not. When you're not in a word if you see a letter (unicode.IsLetter), you change the state variable, and continue as long as you see letters. When you see a non-letter, that gives you the end of the word. Then, you can shuffle the runes between word start+1:word end-1, and continue. – Burak Serdar Sep 15 '19 at 19:01

1 Answers1

0

I'm very new to goland/go.


Avoid writing programs in a new language as if you are still writing programs in an old language.


write code that takes a string and seed. It should return a shuffled string where the 1st and last letters in the word, punctuation and numbers are untouched.

Example:

my name is Nikki. My number is 333

should be

my nmae is Nkiki. My nebumr is 333

Here is a solution written in Go.

package main

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

func shuffle(word []rune, rand *rand.Rand) {
    if len(word) < 4 {
        return
    }
    chars := word[1 : len(word)-1]
    rand.Shuffle(
        len(chars),
        func(i, j int) {
            chars[i], chars[j] = chars[j], chars[i]
        },
    )
}

func scramble(text string, seed int64) string {
    rand := rand.New(rand.NewSource(seed))

    chars := []rune(text)
    inWord := false
    i := 0
    for j, char := range chars {
        if !unicode.IsLetter(char) {
            if inWord {
                shuffle(chars[i:j], rand)
            }
            inWord = false
        } else if !inWord {
            inWord = true
            i = j
        }
    }
    if inWord {
        shuffle(chars[i:len(chars)], rand)
    }
    return string(chars)
}

func main() {
    for _, text := range []string{
        "my name is Nikki. My number is 333",
        "The quick brown fox jumps over the lazy dog.",
        loremipsum,
    } {
        fmt.Printf("%q\n", text)
        fmt.Printf("%q\n", scramble(text, 100))
    }
}

var loremipsum = `
Lorem ipsum dolor sit amet, consectetur adipiscing elit, 
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. 
Ut enim ad minim veniam, 
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. 
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. 
Excepteur sint occaecat cupidatat non proident, 
sunt in culpa qui officia deserunt mollit anim id est laborum.
`

Playground: https://play.golang.org/p/NoHXynQSD4p

Output:

"my name is Nikki. My number is 333"
"my name is Nkiki. My neubmr is 333"
"The quick brown fox jumps over the lazy dog."
"The quick bowrn fox jmups over the lzay dog."
"\nLorem ipsum dolor sit amet, consectetur adipiscing elit, \nsed do eiusmod tempor incididunt ut labore et dolore magna aliqua. \nUt enim ad minim veniam, \nquis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. \nDuis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. \nExcepteur sint occaecat cupidatat non proident, \nsunt in culpa qui officia deserunt mollit anim id est laborum.\n"
"\nLorem isupm dloor sit amet, csttunoecer andiipcsig elit, \nsed do emiousd tepmor idinicdnut ut lorbae et dorloe mgnaa aqilua. \nUt einm ad miinm vinaem, \nquis notursd eioattxceirn ualmlco libroas nisi ut aqiiulp ex ea cdmoomo cuanqesot. \nDius aute iurre dolor in rienreehredpt in vlptuotae vielt esse clulim drlooe eu fuagit nulla ptaaiurr. \nEepuxcter snit ocecacat citapadut non prinodet, \nsnut in cpula qui oficfia dsuenret milolt ainm id est laorbum.\n"
peterSO
  • 158,998
  • 31
  • 281
  • 276