Generate random string to match the goal string with minimum iteration and control statements The following is my python code to find the number of iterations needed to generate random string iteratively to match the input string.
Here I have repeated a similar kind of for loop in both the functions getRandomString() and getMatchString(). I tried to avoid it but couldn't. I want this to be combined together into a single generateString() function with minimum iteration statements. Any suggestions to make it so or any other possible way to make the code better without complicating much?
The input is any string statements like &quot;Hello, World! How Are Y@u doiNG?&quot; and the output is the number of iterations needed to match the input string e.g 408. Your suggestions to improve the code will be helpful.
import random

goalString = input()
stringLen = len(goalString)

alphanum = '''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !@#&amp;()–[{}]:;‘,'?/*1234567890'''
alphaLen = len(alphanum)


def getRandomString():
    randomString = ''
    for i in range(stringLen):
        randomString = randomString + alphanum[random.randrange(alphaLen)]
    
    return randomString 
            

def getMatchString():
    betterString = getRandomString()
    newString = ''
    iteration = 1 #included the iteration of generating randomString
    while betterString != goalString:
        charIndex = [i for i in range(stringLen) if betterString[i] == goalString[i]]
        for i in range(stringLen):
            if i in charIndex:
                newString = newString + betterString[i]
            else:
                newString = newString + alphanum[random.randrange(alphaLen)]
                    
        betterString = newString
        newString = ''
        iteration = iteration + 1
    
    return iteration

print(getMatchString())


Sample Input: &quot;Hello, World! How Are Y@u doiNG?&quot;
Sample Output: 408   ##May change depending on the random iteration##
Find my suggestions below.

goalString = input()

Let the user know what to do, input accepts a string as an argument:
goalString = input('Type a string:')


alphanum = '''abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ !@#&amp;()–[{}]:;‘,'?/*1234567890'''

If you need all printable characters you can use string.printable:
import string

alphabet = string.printable
# alphabet contains: 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!&quot;#$%&amp;'()*+,-./:;&lt;=&gt;?@[\]^_`{|}~

Or choose a combination of other constants in the string module.

Generating a random string
def getRandomString():
    randomString = ''
    for i in range(stringLen):
        randomString = randomString + alphanum[random.randrange(alphaLen)]
    
    return randomString 


Avoid using globals passing the length as an argument
String concatenation can be done more efficiently with join
Use random.choices to avoid the for-loop
PEP 8: function names should be lowercase, with words separated by underscores. Variable names follow the same convention as function names.

def generate_random_string(n):
    alphabet = string.printable
    return ''.join(random.choices(alphabet, k=n))


The function to match the string creates many strings using concatenation. It can be done more efficiently by using a list of booleans (as @rperezsoto suggested).
def get_matching_string(s):
    n = len(s)
    matches = [False] * n
    i = 0
    while not all(matches):
        matches = [matches[i] or s[i] == c for i, c in enumerate(generate_random_string(n))]
        i += 1
    return i

The key part is to use the operator or that &quot;remembers&quot; positive matches.


I want this to be combined together into a single generateString()
function with minimum iteration statements

I would suggest keeping two separate functions as in your first solution. The code will be easier to test and reuse. Additionally, you can extract the logic to request the input and print the result from the function getMatchString with a main function:
def main():
    s = input('Type a string:')
    print(get_matching_string(s))

if __name__ == &quot;__main__&quot;:
    main()