##Task:
You have to write a function `add` which takes two binary numbers as strings and returns their sum as a string.

##Note:
* You are `not allowed to convert binary to decimal & vice versa`.
* The sum should contain `No leading zeroes`.

##Examples:
```
add('111','10'); => '1001'
add('1101','101'); => '10010'
add('1101','10111') => '100100'
```

Difficulty: EASY
Tags: Bit manipulation

Fundamentals
Skill types: Bit manipulation

Starter code:
def add(a,b):
	

Solutions:
def binary_string_to_int(string):
	return sum(((d == '1') * 2 ** i for (i, d) in enumerate(string[::-1])))

def add(a, b):
	return '{:b}'.format(binary_string_to_int(a) + binary_string_to_int(b))


from itertools import zip_longest
ADDER = {('0', '0', '0'): ('0', '0'), ('0', '0', '1'): ('1', '0'), ('0', '1', '0'): ('1', '0'), ('0', '1', '1'): ('0', '1'), ('1', '0', '0'): ('1', '0'), ('1', '0', '1'): ('0', '1'), ('1', '1', '0'): ('0', '1'), ('1', '1', '1'): ('1', '1')}

def add(x, y):
	x = x.lstrip('0')
	y = y.lstrip('0')
	if not x:
		return y or '0'
	elif not y:
		return x
	(sum_digits, carry) = ([], '0')
	for (x_digit, y_digit) in zip_longest(x[::-1], y[::-1], fillvalue='0'):
		(sum_digit, carry) = ADDER[x_digit, y_digit, carry]
		sum_digits.append(sum_digit)
	if carry == '1':
		sum_digits.append(carry)
	return ''.join(sum_digits)[::-1]


def add(a, b):
	(out, ap, bp, r) = ('', list(a.lstrip('0')), list(b.lstrip('0')), 0)
	while len(ap) > 0 or len(bp) > 0 or r > 0:
		(ac, bc) = (ap.pop() if len(ap) > 0 else None, bp.pop() if len(bp) else None)
		total = r + (ac == '1') + (bc == '1')
		out = ('1' if total % 2 else '0') + out
		r = 0 if total < 2 else 1
	return out or '0'


def b2i(b):
	return sum((1 << i for (i, x) in enumerate(b[::-1]) if x == '1'))

def add(a, b):
	return format(b2i(a) + b2i(b), 'b')


def bitAdd(b, co):
	if b == '00':
		if co:
			return ('1', False)
		else:
			return ('0', False)
	if b in ['01', '10']:
		if co:
			return ('0', True)
		else:
			return ('1', False)
	if b == '11':
		if co:
			return ('1', True)
		else:
			return ('0', True)

def add(a, b):
	if len(a) < len(b):
		a = (len(b) - len(a)) * '0' + a
	else:
		b = (len(a) - len(b)) * '0' + b
	bits = [i + j for (i, j) in zip(reversed(a), reversed(b))]
	co = False
	ans = ['' for i in range(len(a))]
	for (i, b) in enumerate(bits):
		(ans[i], co) = bitAdd(b, co)
	if co:
		ans.append('1')
	ans = ''.join(reversed(ans)).lstrip('0')
	if ans == '':
		return '0'
	return ans


from itertools import zip_longest

def add(a, b):
	d = ('00', '01', '10', '11')
	(arr, k) = ([], '0')
	for (m, n) in zip_longest(a[::-1], b[::-1], fillvalue='0'):
		(k, r) = d[(m, n, k).count('1')]
		arr.append(r)
	arr.append(k)
	return ''.join(arr[::-1]).lstrip('0') or '0'


def add(a, b):
	out = ''
	carry = 0
	a = a.lstrip('0')
	b = b.lstrip('0')
	max_l = max(len(a), len(b))
	a = a.rjust(max_l, '0')
	b = b.rjust(max_l, '0')
	for i in range(1, max_l + 1):
		(s, carry) = (carry, 0)
		s += 1 if a[-i] == '1' else 0
		s += 1 if b[-i] == '1' else 0
		carry = s > 1
		out += '01'[s % 2]
	out += '1' * carry
	return out[::-1] if len(out) > 0 else '0'


def add(a, b):
	longer = max(len(a), len(b))
	(a, b) = [x.zfill(longer) for x in [a, b]]
	p = {'000': '00', '001': '10', '010': '10', '011': '01', '100': '10', '101': '01', '110': '01', '111': '11'}
	result = []
	c = '0'
	for (x, y) in zip(reversed(a), reversed(b)):
		(r, c) = p[x + y + c]
		result.append(r)
	if c == '1':
		result.append(c)
	return ''.join(reversed(result)).lstrip('0') or '0'