0

I need to generate a fixed-length string with only 'y' and 'n' in a random order, and the number of 'n' in the string is determined by the variable Njk. The strings must be like 'yyyyynynynyyyyyy' or 'yynyyyynyyynyyyy', and I'll generate a huge amount of strings. Currently I'm doing like the code below. The problem is, to generate 200 strings of length 16, it works fine, but when I try to generate 200 strings of length 33, it takes so much time to execute that is making my work unviable. How can I do it in a optimal/efficient way?

Best regards!

#
chaves = 16
Njk = 3

#Generating a random key state
def rand_estado():
    aux2 = randint(0,1)
    if aux2 == 0:
        estado = 'n'
    if aux2 == 1:
        estado = 'y'
    return estado

#Generating a random combination of key states with fixed number of 'y' and 'n'       
def rand_estado_chaves():
    radialidade = 0
    #The condition that must be satisfied
    while (radialidade != chaves - Njk):
        estado_chaves = "" 
        #For each key
        for i in range(chaves):
            estado_chaves += rand_estado()
            radialidade = estado_chaves.count('y')
    return estado_chaves
2
  • Thank you all guys! It really helped me :D Commented Feb 12, 2020 at 13:16
  • It is highly recommended to accept the answer of your choice by clicking the green checkbox near it.
    – bereal
    Commented Feb 12, 2020 at 16:03

4 Answers 4

1

If you know the size of the final string and the number of N, you can create a list that starts with Njk N and length - Njk Y. Then, shuffle the list and join it.

from random import shuffle

final_size = 16
number_of_n = 3

# ['n', 'n', 'n', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y', 'y']
result = list('n' * number_of_n + 'y' * (final_size - number_of_n))
shuffle(result)
result = ''.join(result)
print(result)

This can output strings like this :

nyyyyyyyynyynyyy

nyyyyyyynyyyynyy

ynyynynyyyyyyyyy

0

You can generate random strings with only 2 characters using random.choices by setting the weights. If you get more or fewer ns than you need, discard and get a new one. Below I did that with a recursive function.

import random

def yn_gen(num_n=5, size=30):
    candidate = random.choices('yn', 
        weights=((size-num_n)/size, num_n/size), 
        k=size)
    if candidate.count('n')==num_n:
        return ''.join(candidate)
    else:
        return yn_gen(num_n, size)

yn_gen()
# returns:
'yynnnnyyyyyyyyyyyyyyyyyyyynyyy'

yn_gen(10, 50)
# returns:
'yynynynnyyyyynyyyyyyynyynnyyyyyyyyyynyynyyyyyyyyyy'
0

Essentially, you need to choose the pre-defined number of positions where ns should be placed, and set everything else to y:

def generate(length, ns):
    result = ['y'] * length
    for i in random.sample(range(length), ns):
        result[i] = 'n'
    return ''.join(result)
0

The random module provides a function called sample that can be used to produce the random patterns very efficiently

from random import sample

size    = 33
count   = 200
NjK     = 7

yn      = ["n"]*NjK + ["y"]*(size-NjK)
results = [ "".join(sample(yn,size)) for _ in range(count) ]

print(results[:3],"...",results[-3:])

this will allow you to generate thousands of long patterns very fast.

Not the answer you're looking for? Browse other questions tagged or ask your own question.