### 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: EASY
Tags: Data structures
Skill types: Data structures

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