Balanced smileys check algorithm 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 &gt; 0 and source[i-1] == ':':
                result.append(source[i-1:i+1])
            else:
                result.append(v)
        elif v == ')':
            if i&gt;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) &gt; 0:
        return False
    return True

def generate_balance_string(source, index, prefix, result):
    if index &gt;= 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?


If number of close parenthesis (excluding the smileys) are ever more than the number of open parenthesis, then parentheses are not balanced.
If number of open parenthesis at the end (excluding the frowns) are more than the close ones, then also the parentheses are not balanced.
A couple of minor style points:



In check_balance() the return can be simplified from:

if len(stack) &gt; 0:
    return False
return True


to:        

return len(stack) &lt;= 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 &gt;= len(source):
        result.append(prefix[:])
    elif source[index] == ':' and source[index + 1] == '(':
        ...