Search code examples
pythonrandomcurly-braces

python randomizer - get random text between curly braces with double nesting level


hey i need to create simple python randomizer. example input:

{{hey|hello|hi}|{privet|zdravstvuy|kak dela}|{bonjour|salut}}, can {you|u} give me advice?

and output should be:

hello, can you give me advice

i have a script, which can do this but only in one nested level

with open('text.txt', 'r') as text:
    matches = re.findall('([^{}]+)', text.read())
words = []
for match in matches:
    parts = match.split('|')
    if parts[0]:
        words.append(parts[random.randint(0, len(parts)-1)])
message = ''.join(words)

this is not enough for me )


Solution

  • Python regex does not support nested structures, so you'll have to find some other way to parse the string.

    Here's my quick kludge:

    def randomize(text):
        start= text.find('{')
        if start==-1: #if there are no curly braces, there's nothing to randomize
            return text
    
        # parse the choices we have
        end= start
        word_start= start+1
        nesting_level= 0
        choices= [] # list of |-separated values
        while True:
            end+= 1
            try:
                char= text[end]
            except IndexError:
                break # if there's no matching closing brace, we'll pretend there is.
            if char=='{':
                nesting_level+= 1
            elif char=='}':
                if nesting_level==0: # matching closing brace found - stop parsing.
                    break
                nesting_level-= 1
            elif char=='|' and nesting_level==0:
                # put all text up to this pipe into the list
                choices.append(text[word_start:end])
                word_start= end+1
        # there's no pipe character after the last choice, so we have to add it to the list now
        choices.append(text[word_start:end])
        # recursively call this function on each choice
        choices= [randomize(t) for t in choices]
        # return the text up to the opening brace, a randomly chosen string, and
        # don't forget to randomize the text after the closing brace 
        return text[:start] + random.choice(choices) + randomize(text[end+1:])