### Background

We **all** know about "balancing parentheses" (plus brackets, braces and chevrons) and even balancing characters that are identical.  

Read that last sentence again, I balanced different characters and identical characters twice and you didn't even notice... :)

### Kata
Your challenge in this kata is to write a piece of code to validate that a supplied string is balanced.

You must determine if all that is open is then closed, and nothing is closed which is not already open!

You will be given a string to validate, and a second string, where each pair of characters defines an opening and closing sequence that needs balancing.

You may assume that the second string always has an even number of characters.

### Example
```python
# In this case '(' opens a section, and ')' closes a section
is_balanced("(Sensei says yes!)", "()")       # => True
is_balanced("(Sensei says no!", "()")         # => False

# In this case '(' and '[' open a section, while ')' and ']' close a section
is_balanced("(Sensei [says] yes!)", "()[]")   # => True
is_balanced("(Sensei [says) no!]", "()[]")    # => False

# In this case a single quote (') both opens and closes a section
is_balanced("Sensei says 'yes'!", "''")       # => True
is_balanced("Sensei say's no!", "''")         # => False
```

Difficulty: introductory

Starter code:

def is_balanced(source, caps):
	

Solutions:
def is_balanced(s, caps):
    stack = []
    openers, closers = caps[::2], caps[1::2]
    for char in s:
        if char in openers:
            if char in closers and stack and stack[-1] == char:
                stack.pop()
            else:
                stack.append(char)
        elif char in closers:
            if not stack or openers[closers.index(char)] != stack[-1]:
                return False
            else:
                stack.pop()
    return not stack

from itertools import cycle 

def is_balanced(source, caps, i = 0):
    it = iter(cycle([ caps[i: i +2] for i in range(0, len(caps), 2) ]) )
    cl = ''.join([ e for e in source if e in caps ] )
    while i<len(source):
        if not cl: return True
        n = next(it)
        if n in cl: cl = cl.replace(n,'')
        i += 1
    return False


def is_balanced(verify, pairs):
    opened,closed,records,same = [],[],[],[]
    for i in range(0, len(pairs), 2):
        opened.append(pairs[i])
        closed.append(pairs[i + 1])
    for i in verify:
        if i in opened and i in closed : same.append(not verify.count(i) & 1)
        elif i in opened : records.append(i)
        elif i in closed:
            if not records:return 0
            if records[-1] == opened[closed.index(i)] : records.pop()
    return not records and all(same)

def is_balanced(source, caps):
    oldLen, source = len(source), ''.join( l for l in source if l in caps )
    while oldLen != len(source):
        oldLen = len(source)
        for i in range(0,len(caps),2):
            source = source.replace(caps[i:i+2],'')
    return len(source)==0

def is_balanced(source, caps):
    matches = dict([(b,a) for a,b in zip(caps[::2],caps[1::2]) ])
    source = [char for char in source if char in caps]
    stack = []
    for char in source:
        if len(stack) == 0: stack.append(char)
        elif matches.get(char) == stack[-1]: del stack[-1]
        else: stack.append(char)
    return len(stack) == 0

from functools import reduce
def is_balanced(source, caps):
    _map = {c2:c1 for c1, c2 in zip(caps[0::2], caps[1::2])}
    red = lambda s, e: s[:-1] if s and s[-1] == _map.get(e) else s + e
    return not reduce(red, [c for c in source if c in caps], '')


def is_balanced(s, caps):
    s = ''.join(i for i in s if i in caps)
    caps = [caps[i:i+2] for i in range(0,len(caps),2)]
    prev = ''
    while s != prev:
        prev = s
        for c in caps:
            s = s.replace(c,'')
    return not s