-2

My attempt:

m = str(input())
# m = list(m)
w = ""
r = ""
num = [int(i) for i in m.split() if i.isdigit()] 
for c in range(0,len(m)-1):
    if m[len(m)-1]:
        for num in w:
            if num.isnumeric():
                w.remove(num)
                num.join(r)
    elif m[c].isalpha():
        r.join(m[c])
    elif m[c].isnumeric() and (len(w)==0 or w[c]=='('):
        w.join(m[c])
    elif len(num)!=0:
        try:
            if int(m[c])>int(w[c]):
                w.join(m[c])
            else:
                n = [int(i) for i in w.split() if i.isdigit()]
                if len(n)!=0:
                    r = ''.join([str(elem) for elem in w]) 
        except:
            continue
    elif m[c]==')':
        for number in m:
            if number.isnumeric():
                w+=number
            elif number=='(':
                m.remove('(')
                m.remove(')')
                break
    elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w=""): # In this statement it gives an invalid syntax error
        w = m[c]
    else:
        break
        
print(r)

I would like to know why get a invalid syntax at line 34 (elif statement). Also, would like to know if there is any better way to solve this question.

Thanks


QUESTION:

Midnumeral Strings to Rightnumeral Strings

Midnumeral string is a string which contains one number in between letters. For example, a1b2c is a midnumeral string. A midnumeral strings may contain letters a to z, numbers 1 to 9 and both left and the right parentheses.

Rightnumeral string is a string which can be formed from midnumeral string: (i) All the characters except left and right parenthesis in the midnumeral string is present in rightnumeral string. (ii) A number ‘n’ which is between letters ‘a’ anb ‘b’ in the midnumeral string will appear in the right hand of side of the letters ‘a’ and ‘b’ in rightnumeral string in a particular fashion. (iii)During the process of conversion of a midnumeral string to a rightnumeral string, a waiting stream is used.

Given a midnumeral string ‘m’ it can be converted to a rightnumeral string ‘r’ as follows:

i. Process character by character of midnumeral string ‘m’.

ii. When a letter is seen add it to rightnumeral string ‘r’.

iii. When a number ‘n’ is seen and waiting stream is empty or the recently added character to waiting stream is left parenthesis then add ‘n’ to waiting stream

iv. If a number ‘n’ seen and there are some numbers in the waiting stream then, If the recently added numeral in waiting stream is less than ‘n’ then add ‘n’ to waiting stream, Otherwise process waiting stream from most recent to least recent:-Remove number from waiting stream and add it to ‘r’

Repeat part (i), until the recent value available in waiting stream is less than ‘n’ or the recent character the waiting stream is left parenthesis or the waiting stream becomes empty

v. Add ‘n’ to the waiting stream

vi. If a left parenthesis is seen then add it to waiting stream

vii. When right parenthesis is seen then remove all numbers from most recent to least recent from waiting stream and add it to r till left parenthesis is seen. Discard left and right parenthesis

viii. When the end of the midnumeral ‘m’ string is reached remove all numerals from most recent to least recent from waiting stream and add it to right numeral string ‘r’

For example,

a1b2c will be abc21

a2b1c will be ab2c1

(a1b)2c will be ab1c2

a1b4(c5d2e)7f will be abcd5e2f741

Note: All the characters in the midnumeral will be distinct and only valid input is given

Input Format

First line contains the midnumeral string, m

Output Format

First line should contain the rightnumeral string, r


Federico Baù
  • 6,013
  • 5
  • 30
  • 38
Arun
  • 27
  • 7
  • 1
    Welcome to [Stack Overflow.](https://stackoverflow.com/ "Stack Overflow"). In order for us to help you, it is necessary that you show your effort and submit data to be used to reproduce your problem. While providing an image is helpful, it doesn't allow for reproducing the issue. Please edit your question to show a minimal reproducible set. See [Minimal Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example "Minimal Reproducible Example") for details. – itprorh66 Jan 14 '21 at 21:13
  • 1
    Post your code into the question as text, not as a link to an external site that hasn't copy enabled. – mhawke Jan 15 '21 at 04:28
  • Huhhh, this was my first question posted, it was extremely complicated, I had to edit it 8-9 times, anyways, it was a learning. Is it fine now or more to do, I just want a simple answer and waiting for almost 12 hours now. – Arun Jan 15 '21 at 04:40
  • 1
    @Arun Add also the error Trace, just copy it and edit the answer – Federico Baù Jan 15 '21 at 08:20

1 Answers1

0

.1 The Syntax error

It is simple a missing '=' sign, so change it to this

elif (w[c]=='(') or ((int(w[c]))<(int(m[c]))) or (w==""):
        w = m[c]
    else:
        break

.2 Code improvements & Best practices

I suggest you for this to post the answer on Code Review as is meant for this. There are quite few errors and not best practices follow.

For instance, this error block:

       try:
            if int(m[c])>int(w[c]):
                w.join(m[c])
            else:
                n = [int(i) for i in w.split() if i.isdigit()]
                if len(n)!=0:
                    r = ''.join([str(elem) for elem in w]) 
        except:
            continue

The except is catching too many types of error, better like:

       try:
          if int(m[c])>int(w[c]):
              w.join(m[c])
          else:
              n = [int(i) for i in w.split() if i.isdigit()]
              if len(n)!=0:
                  r = ''.join([str(elem) for elem in w]) 
        except ValueError:
            continue

Have a look at Should I always specify an exception type in except statements? for more information about this. Also there is too much 'logic' in that try block. but for simplicity that is ok.



EDIT

Consideration

  1. Note that I used different combination of sets ( accepted_numbers, accepted_chars, left_parenthesis, right_parenthesis) instead of list of other thing, this is because set are super fast when used for Looks up, more info --> Time complexity of python set operations?. And also is very clear what you are trying to use them for.

  2. The Variable r, is way better decision to use it during the Algorithm as a List and Then turn it as a String, that's because is just easier to manipulate.

  3. I don't even used 1 try except block, this is because, is was clear what to do, I mean we knew it ahead, so you can just handle it with a if else block, apart of what I stated Above regarding the Try blocks, another important aspect is that the slow down the code if finds and exception (in this code it won't even matter) look here try-except vs If in Python

  4. The Algorithm problem that you posted uses and demands a Stack as a Collection, you can see it implemented in the process_waiting_stream() function in a LIFO (last in, first out) fashion.

process_waiting_stream()

Answer Testing one case

m = '(a1b)2c'  # test string Added on the top as requested in the exercise 
import string  # If you don't want to import string, just hard code the letters


m = m
r = []

# ----- CONSTANTS
accepted_numbers = {str(i) for i in range(1, 10)}  # 1 to 9
accepted_chars = {*string.ascii_lowercase}
left_parenthesis = '('
right_parenthesis = ')'
parenthesis = {left_parenthesis, right_parenthesis}
midnumeral_string  = accepted_numbers | accepted_chars | parenthesis


#  ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
for char in m:
    if char in midnumeral_string:
        pass
    else:
        print('Input String is not a Midnumeral string')
        continue
# ---------------------------
WAITING_STREAM = []
r = [] # Use a list, not a string, easier to work with :) 

def process_waiting_stream():
    global WAITING_STREAM

    if WAITING_STREAM:
        WAITING_STREAM.reverse() # LIFO  from most recent to least recent
        while True:
            if not WAITING_STREAM:
                break
            item = WAITING_STREAM[0]
            if item == left_parenthesis:
                    break      
            elif item in accepted_numbers:
                item = WAITING_STREAM.pop(0)
                r.append(item)
        WAITING_STREAM.reverse() 

def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
    return any([item in accepted_numbers for item in WAITING_STREAM])



for char in m:
    if WAITING_STREAM:
        recently_added = WAITING_STREAM[-1]
    
    if char in accepted_chars:  
        r.append(char)            
    elif char in accepted_numbers:   

        if not WAITING_STREAM or recently_added == left_parenthesis:
            WAITING_STREAM.append(char)                    

        elif checK_stream(): 
            if (recently_added not in parenthesis 
                and recently_added not in accepted_chars) and int(recently_added) < int(char):
                WAITING_STREAM.append(char)
            else:
                process_waiting_stream() 
                WAITING_STREAM.append(char)
        else:
            WAITING_STREAM.append(char)

    elif char == left_parenthesis:
        WAITING_STREAM.append(char)

    elif char == right_parenthesis:
        process_waiting_stream()

   
for item in WAITING_STREAM:
    if item == left_parenthesis:
        left_para = WAITING_STREAM.index(left_parenthesis)
        WAITING_STREAM.pop(left_para)
        break

process_waiting_stream()        

r = ''.join(r)
print(r)

Answer 2

Testing All cases

import string  # If you don't want to import string, just hard code the letters

def rightnumeral_string(m):

    # ----- CONSTANTS
    accepted_numbers = {str(i) for i in range(1, 10)}  # 1 to 9
    accepted_chars = {*string.ascii_lowercase}
    left_parenthesis = '('
    right_parenthesis = ')'
    parenthesis = {left_parenthesis, right_parenthesis}
    midnumeral_string  = accepted_numbers | accepted_chars | parenthesis


    #  ---- NOTE: Run a quick check is Input is Correct |!(a1b)2c or (a1b)0c is not good
    for char in m:
        if char in midnumeral_string:
            pass
        else:
            print('Input String is not a Midnumeral string')
            continue
    # ---------------------------
    WAITING_STREAM = []
    r = [] # Use a list, not a string, easier to work with :) 

    def process_waiting_stream():
        nonlocal WAITING_STREAM

        if WAITING_STREAM:
            WAITING_STREAM.reverse() # LIFO  from most recent to least recent
            while True:
                if not WAITING_STREAM:
                    break
                item = WAITING_STREAM[0]
                if item == left_parenthesis:
                        break      
                elif item in accepted_numbers:
                    item = WAITING_STREAM.pop(0)
                    r.append(item)
            WAITING_STREAM.reverse() 
    
    def checK_stream(): # NOTE: We check this in case there is only '(' and not a num
        return any([item in accepted_numbers for item in WAITING_STREAM])


    # ------ Iterate Through each Character (number included) in the string
    for char in m:

        if WAITING_STREAM:  
            recently_added = WAITING_STREAM[-1]  
        if char in accepted_chars:  
            r.append(char)            
        elif char in accepted_numbers:   

            if not WAITING_STREAM or recently_added == left_parenthesis:
                WAITING_STREAM.append(char)                    

            elif checK_stream(): # Check if there are currently nums in stream
                if (recently_added not in parenthesis 
                    and recently_added not in accepted_chars) and int(recently_added) < int(char):
                    WAITING_STREAM.append(char)
                else:
                    process_waiting_stream() 
                    WAITING_STREAM.append(char)
            else:
                WAITING_STREAM.append(char)

        elif char == left_parenthesis:
            WAITING_STREAM.append(char)

        elif char == right_parenthesis:
            process_waiting_stream()

    # Last Step is to Remove left_parenthesis
    for item in WAITING_STREAM:
        if item == left_parenthesis:
            left_para = WAITING_STREAM.index(left_parenthesis)
            WAITING_STREAM.pop(left_para)
            break
    
    process_waiting_stream()        

    r = ''.join(r)
    return r

print(rightnumeral_string('a1b2c'))
print(rightnumeral_string('a2b1c'))
print(rightnumeral_string('(a1b)2c'))
print(rightnumeral_string('a1b4(c5d2e)7f'))

# Checking if the Answer Are correct
assert rightnumeral_string('a1b2c') == 'abc21'
assert rightnumeral_string('a2b1c') == 'ab2c1'
assert rightnumeral_string('(a1b)2c') == 'ab1c2'
assert rightnumeral_string('a1b4(c5d2e)7f') == 'abcd5e2f741'

Documentation

Federico Baù
  • 6,013
  • 5
  • 30
  • 38
  • I am a beginner in this, can you please help me with a solution, I get no solution at all (just a new line, probably it is the value of 'r' which is empty)... – Arun Jan 15 '21 at 11:32
  • @Arun I can however I'm not able to come up with solution right now as I'm working. I like to solve this kind of problems. So you should have patient I may take me sometimes, maybe I can in few hours. One thing If then my answer is good and not one answer remember to mark my answer as accepted ok? – Federico Baù Jan 15 '21 at 11:41
  • @Arun I did make and example, if you have question feel free. If it helpd rember to accept my answer. so it can be removed from the unanswered list – Federico Baù Jan 15 '21 at 16:21