J. Bauer
J. Bauer

Reputation: 45

Scrambling a string in Python without using random.shuffle()

I'm trying to scramble a string, "string", without using random.shuffle(), but my code keeps producing output that has missing and repeating characters, e.g. gtrgtg, gnrtnn, etc. I'm not sure what I'm doing wrong.

    import random
    s = "string"
    new_s=[]
    for c in s:
      if random.choice(s) not in new_s:
        new_s.append(random.choice(s))

    print(''.join(new_s))

Upvotes: 0

Views: 3278

Answers (4)

SKN
SKN

Reputation: 2612

Using while, you could loop through s until the length of new_s matches with that of s and the resultant string has non-repeating characters.

import random

s = "string"
new_s = ''  # So you will not need ''.join() when you print this result

while len(new_s) != len(s):
    char = random.choice(s)
    if char not in new_s:
        new_s += char

print(new_s)

rntigs
>>> 

Upvotes: 1

user2285236
user2285236

Reputation:

In its current state, your program checks whether the randomly chosen character is in a string. If it is, it doesn't do anything other than continuing the loop. Also since you don't assign random.choice(s) to a variable, you generate another character after you do the check.

A working version would be:

import random
s = "string"
new_s = []
for c in s:
    char = random.choice(s)  # assign it to a variable
    while char in new_s:  # until a new character comes, repeat the procedure
        char = random.choice(s)
    new_s.append(char)

print(''.join(new_s))

This generates strings like ngtsri, gsrnit, etc. Note that this won't work if you have duplicates in the original string.

The above code is highly inefficient. I only gave the correction assuming this was for learning purposes. Normally, if you want to repeatedly check if something is in a collection, that collection should be a set or a dictionary.

Upvotes: 3

Dan Gittik
Dan Gittik

Reputation: 3850

random.choice choses a random character out of string s, but doesn't remove it - so it's possible for the same character to be chosen multiple times, and for some characters to not be chosen at all.

import random

s = 'string'
new_s = []

# rather than choosing a character, chose an index, use it and slice it out
while s:
    i = random.randint(0, len(s)-1)
    new_s.append(s[i])
    s = s[:i] + s[i+1:]
print(''.join(new_s))

# this is more elegant with lists:
s = list(s)
while s:
    i = random.randint(0, len(s)-1)
    new_s.append(s.pop(i))
print(''.join(new_s))

Neither option is very efficient... but for efficiency, use random.shuffle. :)

Upvotes: 1

mehdi maick
mehdi maick

Reputation: 325

try this:

from random import randint

def shuffle(sr):
    n = len(sr)
    s = list(sr)
    for i in range(n):
        cur, idx = s[i], randint(0, n - 1)
        s[i], s[idx] = s[idx], cur
    return ''.join(s)

print(shuffle("hello"))

Upvotes: 0

Related Questions