How to change the cycle of getting correct answers?

I have a task to create a function that reverses any string character within a regular sequence of brackets, starting with the innermost pair. The sequence of lines can contain spaces, punctuation marks, letters and marriages. Therefore, the result must be a sting.

Example

For string

s = "a(bc)de"

      

the output should be

reverseParentheses(s) = "acbde".

      

To solve this problem, I wrote the following code:

s_i = s   
for i in range(s.count('(')):
    # reverse letters inside parenthesis
    s_i = s_i.replace(s_i[s_i.rindex('(')+1:s_i.index(')')], s_i[s_i.rindex('(')+1:s_i.index(')')][::-1])
    # delete outward parenthesis
    s_i =s_i[:s_i.rindex('(')] + s_i[s_i.rindex('(')+1:]
    # delete inward parenthesis
    s_i =s_i[:s_i.index(')')] + s_i[s_i.index(')')+1:]
    i += 1
print(s_i)

      

However, I am getting false results for the following lines:

s = "abc(cba)ab(bac)c"

      

It should be

abcabcabcabc

      

I get

abccabbaabcc

      

AND

s = "The ((quick (brown) (fox) jumps over the lazy) dog)"

      

It should be like this:

The god quick nworb xof jumps over the lazy

      

But I only get:

The god quick xof nworb jumps over the lazy

      

How do I fix or tweak my code to get correct results for the last two examples?

Correction of the code

I tried to take the answers and hints into account, but I couldn't use recursion. I looked into the problem with parameters when there are only two of them:"..(...) (...).., .."

So, I did the following code:

def reverse(s):
#ensure parens are in pairs
if '(' not in s and ')' not in s:
    while '(' in s:
            s = s.replace(s[s.rindex('(')+1:s.index(')')], s[s.rindex('(')+1:s.index(')')][::-1])
            s = s[:s.rindex('(')] + s[s.rindex('(')+1:]
            s = s[:s.index(')')] + s[s.index(')')+1:]
    return s
else:
    if (s[s.index(')'):s.rindex('(')+1] == ''):
        while '(' in s:
                s = s.replace(s[s.rindex('(')+1:s.index(')')], s[s.rindex('(')+1:s.index(')')][::-1])
                s = s[:s.rindex('(')] + s[s.rindex('(')+1:]
                s = s[:s.index(')')] + s[s.index(')')+1:]
        return s
    elif (s[s.index(')'):s.rindex('(')+1] != ''):
        betw = s[s.index(')')+1:s.rindex('(')]
        part1 = s[:s.index(')')+1]
        part2 = s[s.rindex('('):]
        part1 = part1.replace(part1[part1.rindex('(')+1:part1.index(')')], part1[part1.rindex('(')+1:part1.index(')')][::-1])
        part1 = part1[:part1.rindex(')')]
        part2 = part2.replace(part2[part2.rindex('(')+1:part2.index(')')], part2[part2.rindex('(')+1:part2.index(')')][::-1])
        part2 = part2[part2.rindex('(')+1:]
        s = part1+betw+part2
        s = s[:s.rindex('(')] + s[s.rindex('(')+1:]
        s = s[:s.index(')')] + s[s.index(')')+1:]
        while '(' in s:
            s = s.replace(s[s.rindex('(')+1:s.index(')')], s[s.rindex('(')+1:s.index(')')][::-1])
            s = s[:s.rindex('(')] + s[s.rindex('(')+1:]
            s = s[:s.index(')')] + s[s.index(')')+1:]
        return s
    else:
        while '(' in s:
            s = s.replace(s[s.rindex('(')+1:s.index(')')], s[s.rindex('(')+1:s.index(')')][::-1])
            s = s[:s.rindex('(')] + s[s.rindex('(')+1:]
            s = s[:s.index(')')] + s[s.index(')')+1:]
        return s

      

However, I think it may not work well for the following example:

s = "abc(147)ab(123)c(12)asd"

      

The answer should be: "abc741ab321c21asd"

but I am getting"abc12c321ba147asd"

What needs to be changed to get the correct answer?

+3


source to share


3 answers


rather than doing it manually, use a module regexre

that specializes in string handling

import re

def reverseParentheses(s):
    def reverse_interior(m):
        s = m.group()
        return s[-2:0:-1]
    old = ""
    while old != s:
        old = s
        s = re.sub(r'(\([^\(\)]*\))',reverse_interior,s)
    return s

assert reverseParentheses("a(bc)de") == "acbde"
assert reverseParentheses("abc(cba)ab(bac)c") == "abcabcabcabc"
assert reverseParentheses("The ((quick (brown) (fox) jumps over the lazy) dog)") == "The god quick nworb xof jumps over the lazy"
assert reverseParentheses("((ob))") == "ob"

      



here the expression '(\([^\(\)]*\))'

will search for everything between (

and )

that is one of the characters defined in [^\(\)]*

, which in turn means any character of numbers that is not (

or )

so it will search for the innermost group that will match, then I am using the re.sub function to replace the ones contained in the string with this helper function that takes a form string "(xyz)"

and returns "zyx"

. Since this is the only job for the inner group itself, the process should be repeated as long as there are changes to be made, hence the cycle.

+1


source


The reason your solution doesn't work is because it doesn't match the parentheses:

"abc(cba)ab(bac)c"
"   (cba)ab(bac) "
"       )ab(     "

      

Your method will ultimately fail: instead, I recommend that you figure out the best way to figure out which pairs match:



def find_paren_set(str):
    # magic
    return left, right

      

Once you have this opportunity, you can just while has_parens(str):

until you finish.

Additional note: every time you change a section, the internal partners will be replaced, ((ob))

will become )bo(

.

+1


source


Since it seems like there can be any number of pairs ()

, I would recommend implementing a recursive function that can be called as long as the pairs of partners still exist at a level beyond the first:

def reverseParentheses(s):
    # ensure parens are in pairs
    assert '(' in s and ')' in s

    while '(' in s:
        # Go through and swap strings/letters in the innermost parens only.
        # Then reassign `s` to that newly formatted string 
        #  (after taking out those parens)
        # Call the function again until it purges the string of all parens
        reverseParentheses(s)
    return s

      

+1


source







All Articles