3
\$\begingroup\$

Problem

Your friend John uses a lot of emoticons when you talk to him on Messenger. In addition to being a person who likes to express himself through emoticons, he hates unbalanced parenthesis so much that it makes him go :(

Sometimes he puts emoticons within parentheses, and you find it hard to tell if a parenthesis really is a parenthesis or part of an emoticon.

A message has balanced parentheses if it consists of one of the following:

  • An empty string ""
  • One or more of the following characters: 'a' to 'z', ' ' (a space) or ':' (a colon)
  • An open parenthesis '(', followed by a message with balanced parentheses, followed by a close parenthesis ')'.
  • A message with balanced parentheses followed by another message with balanced parentheses.
  • A smiley face ":)" or a frowny face ":("
  • Write a program that determines if there is a way to interpret his message while leaving the parentheses balanced.

I'm working on this balanced smileys checking algorithm, and my current solution is very naive, just enumerate all possible ways to interpret :) and :(. I'm wondering if any smarter ideas in terms of algorithm time complexity perspective.

def procee_raw_string(source):
 result = []
 for i,v in enumerate(source):
 if v == '(':
 if i > 0 and source[i-1] == ':':
 result.append(source[i-1:i+1])
 else:
 result.append(v)
 elif v == ')':
 if i>0 and source[i-1] == ':':
 result.append(source[i-1:i+1])
 result.append(')')
 return ''.join(result)
def check_balance(source):
 stack = []
 for s in source:
 if s == '(':
 stack.append(s)
 else: # s is ')'
 if len(stack) == 0 or stack[-1] != '(':
 return False
 else:
 stack.pop(-1)
 if len(stack) > 0:
 return False
 return True
def generate_balance_string(source, index, prefix, result):
 if index >= len(source):
 result.append(prefix[:])
 return
 if source[index] == ':' and source[index+1] == '(':
 prefix.append('(')
 generate_balance_string(source, index+2, prefix, result)
 prefix.pop(-1)
 generate_balance_string(source, index+2, prefix, result)
 elif source[index] == ':' and source[index+1] == ')':
 prefix.append(')')
 generate_balance_string(source, index+2, prefix, result)
 prefix.pop(-1)
 generate_balance_string(source, index+2, prefix, result)
 elif source[index] == '(':
 prefix.append('(')
 generate_balance_string(source, index+1, prefix, result)
 prefix.pop(-1)
 elif source[index] == ')':
 prefix.append(')')
 generate_balance_string(source, index+1, prefix, result)
 prefix.pop(-1)
if __name__ == "__main__":
 raw_smile_string = 'abc(b:)cdef(:()'
 process_string = procee_raw_string(raw_smile_string)
 result = []
 generate_balance_string(process_string, 0, [], result)
 for r in result:
 print check_balance(r)

Additional thoughts,

I am not sure if we could do such simple check for balance?

  1. If number of close parenthesis (excluding the smileys) are ever more than the number of open parenthesis, then parentheses are not balanced.
  2. If number of open parenthesis at the end (excluding the frowns) are more than the close ones, then also the parentheses are not balanced.
asked Jan 16, 2017 at 6:16
\$\endgroup\$
3
  • 1
    \$\begingroup\$ Could you please check this code for PEP8, as well as providing some nicely formatted output for you test? \$\endgroup\$ Commented Jan 16, 2017 at 7:45
  • \$\begingroup\$ @Seanny123, I check for each possible interpret and it will return True and False for each interpret, for example, in the test case I posted, one of the choice returns True, which means the raw input is balanced. \$\endgroup\$ Commented Jan 16, 2017 at 7:57
  • 1
    \$\begingroup\$ @Seanny123, for PEB8, since I am using Pycharm, I corrected most of them which I think are major. I leave some alerts since I think they are too heavy for such simple program. If you have any thoughts on my original questions, it will be great. \$\endgroup\$ Commented Jan 16, 2017 at 7:57

1 Answer 1

2
\$\begingroup\$

A couple of minor style points:


In check_balance() the return can be simplified from:

if len(stack) > 0:
 return False
return True

to:

return len(stack) <= 0

In generate_balance_string() there is a long if/elif string. But the first element does not follow the pattern and has an embedded return it does not need. You can drop the return and make the following if an elif to make your code more uniform:

def generate_balance_string(source, index, prefix, result):
 if index >= len(source):
 result.append(prefix[:])
 elif source[index] == ':' and source[index + 1] == '(':
 ...
answered Jan 16, 2017 at 19:00
\$\endgroup\$
2
  • \$\begingroup\$ Thanks Stephen, vote up for your reply and I have found another simpler solution, I post here (codegolf.stackexchange.com/questions/107049/…), if you have any advice it will be great. For your above comments, I will study and reply later. \$\endgroup\$ Commented Jan 16, 2017 at 20:20
  • \$\begingroup\$ Thanks Stephen, accept all of your comments and vote up. If you have any advice on my new post above (codegolf.stackexchange.com/questions/107049/…), it will be great. \$\endgroup\$ Commented Jan 18, 2017 at 6:02

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.