Introduction
Brainfuck is one of the most well-known esoteric programming languages. But it can be hard to understand any code longer that 5 characters. In this kata you have to solve that problem.

Description

In this kata you have to write a function which will do 3 tasks:

Optimize the given Brainfuck code.
Check it for mistakes.
Translate the given Brainfuck programming code into C programming code.


More formally about each of the tasks:



Your function has to remove from the source code all useless command sequences such as: '+-', '<>', '[]'. Also it must erase all characters except +-<>,.[].
Example:
"++--+." -> "+."
"[][+++]" -> "[+++]"
"<>><" -> ""


If the source code contains unpaired braces, your function should return "Error!" string.


Your function must generate a string of the C programming code as follows:




Sequences of the X commands + or - must be replaced by \*p += X;\n or \*p -= X;\n.
Example:
"++++++++++" -> "\*p += 10;\n"
"------" -> "\*p -= 6;\n"



Sequences of the Y commands > or < must be replaced by p += Y;\n or p -= Y;\n.
Example:
">>>>>>>>>>" -> "p += 10;\n"
"<<<<<<" -> "p -= 6;\n"



. command must be replaced by putchar(\*p);\n.
Example:
".." -> "putchar(\*p);\nputchar(\*p);\n"



, command must be replaced by \*p = getchar();\n.
Example:
"," -> "\*p = getchar();\n"



[ command must be replaced by if (\*p) do {\n. ] command must be replaced by } while (\*p);\n.
Example:
"[>>]" ->
if (\*p) do {\n
  p += 2;\n
} while (\*p);\n



Each command in the code block must be shifted 2 spaces to the right accordingly to the previous code block.
Example:
"[>>[<<]]" ->
if (\*p) do {\n
  p += 2;\n
  if (\*p) do {\n
    p -= 2;\n
  } while (\*p);\n
} while (\*p);\n





Examples

Input:
+++++[>++++.<-]
Output:
*p += 5;
if (*p) do {
  p += 1;
  *p += 4;
  putchar(*p);
  p -= 1;
  *p -= 1;
} while (*p);

Source: codewars | Difficulty: MEDIUM
Tags: String algorithms

Starter code: def brainfuck_to_c(source_code):
	

Solutions:
import re

def brainfuck_to_c(source):
	source = re.sub('[^+-<>,.\\[\\]]', '', source)
	before = ''
	while source != before:
		before = source
		source = re.sub('\\+-|-\\+|<>|><|\\[\\]', '', source)
	braces = re.sub('[^\\[\\]]', '', source)
	while braces.count('[]'):
		braces = braces.replace('[]', '')
	if braces:
		return 'Error!'
	commands = re.findall('\\++|-+|>+|<+|[.,\\[\\]]', source)
	output = []
	indent = 0
	for cmd in commands:
		if cmd[0] in '+-<>':
			line = '%sp %s= %s;\n' % ('*' if cmd[0] in '+-' else '', '+' if cmd[0] in '+>' else '-', len(cmd))
		elif cmd == '.':
			line = 'putchar(*p);\n'
		elif cmd == ',':
			line = '*p = getchar();\n'
		elif cmd == '[':
			line = 'if (*p) do {\n'
		elif cmd == ']':
			line = '} while (*p);\n'
			indent -= 1
		output.append('  ' * indent + line)
		if cmd == '[':
			indent += 1
	return ''.join(output)


def brainfuck_to_c(s):
	s = ''.join((c for c in s if c in '.,<>[]-+'))
	pairs = '<> >< -+ +- []'.split()
	while any((p in s for p in pairs)):
		for w in pairs:
			s = s.replace(w, '')
	(r, depth, l, i) = ('', 0, ' ', 1)
	for c in s:
		if c == l and c in '<>+-':
			i += 1
			continue
		if l in '<>+-':
			r += cmd(depth, l, i)
		if c == ']':
			depth -= 2
		if c in '.,[]':
			r += cmd(depth, c)
		if c == '[':
			depth += 2
		if depth < 0:
			break
		(i, l) = (1, c)
	return 'Error!' if depth else r + (cmd(depth, l, i) if l in '<>+-' else '')

def cmd(depth, c, i=None):
	return ' ' * depth + {'<': 'p -=', '>': 'p +=', '+': '*p +=', '-': '*p -=', '.': 'putchar(*p);', ',': '*p = getchar();', '[': 'if (*p) do {', ']': '} while (*p);'}[c] + (' {};'.format(i) if i else '') + '\n'


import re

def brainfuck_to_c(sc):
	(code, p, l, t) = ([], 0, -1, 0)
	while l != len(sc):
		l = len(sc)
		sc = re.sub('(\\+\\-)|(\\-\\+)|(<>)|(><)|(\\[\\])|[^+\\-<>,.\\[\\]]', '', sc)
	(l, braces) = (-1, re.sub('[+\\-.<>,]', '', sc))
	while l != len(braces):
		l = len(braces)
		braces = re.sub('(\\[\\])', '', braces)
	if len(braces) != 0:
		return 'Error!'
	while p < len(sc):
		c = sc[p]
		if c in '+-><':
			if c == '+':
				(m, v, o) = ('+', '*', '+')
			elif c == '-':
				(m, v, o) = ('-', '*', '-')
			elif c == '>':
				(m, v, o) = ('>', '', '+')
			elif c == '<':
				(m, v, o) = ('<', '', '-')
			n = re.match('\\' + m + '+', sc[p:]).group()
			p += len(n) - 1
			code.append(' ' * t + v + 'p ' + o + '= ' + str(len(n)) + ';')
		elif c == '.':
			code.append(' ' * t + 'putchar(*p);')
		elif c == ',':
			code.append(' ' * t + '*p = getchar();')
		elif c == '[':
			code.append(' ' * t + 'if (*p) do {')
			t += 2
		else:
			t -= 2
			code.append(' ' * t + '} while (*p);')
		p += 1
	return '' if sc == '' else '\n'.join(code) + '\n'


import re, itertools
WORDING = dict(map(lambda x: x.split(' | '), '\n- | *p -= %s;\n+ | *p += %s;\n< | p -= %s;\n> | p += %s;\n[ | if (*p) do {\n] | } while (*p);\n. | putchar(*p);\n, | *p = getchar();\n'.splitlines()[1:]))

def brainfuck_to_c(source_code):
	(code, old_code) = (source_code, '')
	while code != old_code:
		old_code = code
		code = re.sub('[^\\+\\-\\<\\>\\[\\]\\.\\,]+|\\+\\-|\\-\\+|\\<\\>|\\>\\<|\\[\\]', '', code)
	(indent, output) = (0, [])
	for (command, sequence) in itertools.groupby(code):
		repeat = len(list(sequence))
		if command in '+-<>':
			output += [indent * ' ' + WORDING[command] % repeat]
		if command in '.,[]':
			for i in range(repeat):
				indent -= 2 * (command is ']')
				output += [indent * ' ' + WORDING[command]]
				indent += 2 * (command is '[')
		if indent < 0:
			break
	return 'Error!' if indent else '\n'.join(output + [''])


class BFCore(object):
	STR_C = ''

	def __init__(self, delta=0, val=''):
		self.delta = delta
		self.val = val

	def __repr__(self):
		return '{}({},{})'.format(self.__class__.__name__, self.val, self.delta)

	def __bool__(self):
		return True

	def toC(self):
		return ' ' * self.delta + self.STR_C

class ValMov(BFCore):

	def toC(self):
		return self.STR_C.format(' ' * self.delta, '+' if self.val > 0 else '-', abs(self.val))

	def __iadd__(self, n):
		self.val += n
		return self

	def __bool__(self):
		return self.val != 0

class Val(ValMov):
	STR_C = '{}*p {}= {};\n'

class Mov(ValMov):
	STR_C = '{}p {}= {};\n'

class LoopOpen(BFCore):
	STR_C = 'if (*p) do {\n'

class LoopClose(BFCore):
	STR_C = '} while (*p);\n'

class Input(BFCore):
	STR_C = '*p = getchar();\n'

class Output(BFCore):
	STR_C = 'putchar(*p);\n'

def brainfuck_to_c(source):
	(lst, delta) = ([BFCore()], 0)
	for c in source:
		if c in '-+':
			if isinstance(lst[-1], Val):
				lst[-1] += 1 if c == '+' else -1
				if not lst[-1]:
					del lst[-1]
			else:
				lst.append(Val(delta, 1 if c == '+' else -1))
		elif c in '<>':
			if isinstance(lst[-1], Mov):
				lst[-1] += 1 if c == '>' else -1
				if not lst[-1]:
					del lst[-1]
			else:
				lst.append(Mov(delta, 1 if c == '>' else -1))
		elif c == '[':
			lst.append(LoopOpen(delta))
			delta += 2
		elif c == ']':
			delta -= 2
			if delta < 0:
				return 'Error!'
			if isinstance(lst[-1], LoopOpen):
				del lst[-1]
			else:
				lst.append(LoopClose(delta))
		elif c == ',':
			lst.append(Input(delta))
		elif c == '.':
			lst.append(Output(delta))
	return 'Error!' if delta != 0 else ''.join((tok.toC() for tok in lst))


def brainfuck_to_c(source_code):
	result = ''
	possible = '+-<>,.[]'
	spacing = 0
	braces_count = 0
	op_count = 0
	source_code = ''.join((letter for letter in source_code if letter in possible))
	while '[]' in source_code or '+-' in source_code or '<>' in source_code or ('-+' in source_code) or ('><' in source_code):
		source_code = source_code.replace('[]', '').replace('+-', '').replace('<>', '').replace('-+', '').replace('><', '')
	if source_code.count('[') != source_code.count(']'):
		return 'Error!'
	for (index, letter) in enumerate(source_code):
		if letter == '[':
			braces_count += 1
			result += ' ' * spacing + 'if (*p) do {\n'
			spacing += 2
		elif letter == ']':
			braces_count -= 1
			if braces_count < 0:
				return 'Error!'
			spacing -= 2
			result += ' ' * spacing + '} while (*p);\n'
		elif letter == '+' or letter == '-':
			if index < len(source_code) - 1 and source_code[index + 1] == letter:
				op_count += 1
				continue
			else:
				result += ' ' * spacing + f'*p {letter}= {op_count + 1};\n'
				op_count = 0
		elif letter == '<' or letter == '>':
			if index < len(source_code) - 1 and source_code[index + 1] == letter:
				op_count += 1
				continue
			else:
				equi = '+' if letter == '>' else '-'
				result += ' ' * spacing + f'p {equi}= {op_count + 1};\n'
				op_count = 0
		elif letter == '.':
			result += ' ' * spacing + 'putchar(*p);\n'
		elif letter == ',':
			result += ' ' * spacing + '*p = getchar();\n'
	if braces_count != 0:
		return 'Error!'
	return result


from itertools import groupby
import re

def brainfuck_to_c(sc):
	sc = remove(sc, sc)
	(bracket, space, code) = ([], '', '')
	for (i, j) in groupby(sc):
		n = len(list(j))
		if i in '-+':
			code += space + f"*p {'+-'[i == '-']}= {n};\n"
		elif i in '<>':
			code += space + f"p {'+-'[i == '<']}= {n};\n"
		elif i == '.':
			code += (space + 'putchar(*p);\n') * n
		elif i == ',':
			code += (space + '*p = getchar();\n') * n
		elif i == '[':
			for n in range(n):
				code += space + 'if (*p) do {\n'
				space += '  '
				bracket.append('[')
		elif i == ']':
			for n in range(n):
				if not bracket or bracket.pop() != '[':
					return 'Error!'
				space = space[:-2]
				code += space + '} while (*p);\n'
	return 'Error!' if bracket else code

def remove(prev, sc):
	sc = re.sub('\\[\\]', '', re.sub('<>|><', '', re.sub('\\+-|-\\+', '', re.sub('[^\\+-<>,.\\[\\]]', '', sc))))
	return sc if sc == prev else remove(sc, sc)


import re

class Token(object):
	ARITH = 1
	POINTER = 2
	GETCHAR = 3
	PUTCHAR = 4
	OPEN = 5
	CLOSE = 6

	def __init__(self, mode=None, indent=None, value=None):
		self.mode = mode
		self.value = value
		self.indent = indent

	def __str__(self):
		if self.mode == self.ARITH:
			sign = '+' if self.value > 0 else '-'
			return '{}*p {}= {};\n'.format(self.indent, sign, abs(self.value))
		if self.mode == self.POINTER:
			sign = '+' if self.value > 0 else '-'
			return '{}p {}= {};\n'.format(self.indent, sign, abs(self.value))
		if self.mode == self.GETCHAR:
			return self.indent + '*p = getchar();\n'
		if self.mode == self.PUTCHAR:
			return self.indent + 'putchar(*p);\n'
		if self.mode == self.OPEN:
			return self.indent + 'if (*p) do {\n'
		if self.mode == self.CLOSE:
			return self.indent + '} while (*p);\n'
		return ''

class BF(object):
	ARITH = 1
	POINTER = 2
	GETCHAR = 3
	PUTCHAR = 4
	OPEN = 5
	CLOSE = 6

	def __init__(self, source_code):
		self.indent = ''
		self.source_code = source_code
		self.tokens = [Token()]
		self.error = False

	def convert_to_c(self):
		try:
			for c in self.source_code:
				self.convert_one_char(c)
		except ValueError:
			return 'Error!'
		if self.indent:
			return 'Error!'
		return ''.join(map(str, self.tokens))

	def convert_one_char(self, c):
		if c in '+-':
			if self.tokens[-1].mode != self.ARITH:
				self.tokens.append(Token(self.ARITH, self.indent, 0))
			if c == '+':
				self.tokens[-1].value += 1
			else:
				self.tokens[-1].value -= 1
			if not self.tokens[-1].value:
				del self.tokens[-1]
		elif c in '><':
			if self.tokens[-1].mode != self.POINTER:
				self.tokens.append(Token(self.POINTER, self.indent, 0))
			if c == '>':
				self.tokens[-1].value += 1
			else:
				self.tokens[-1].value -= 1
			if not self.tokens[-1].value:
				del self.tokens[-1]
		elif c == ',':
			self.tokens.append(Token(self.GETCHAR, self.indent, 0))
		elif c == '.':
			self.tokens.append(Token(self.PUTCHAR, self.indent, 0))
		elif c == '[':
			self.tokens.append(Token(self.OPEN, self.indent, 0))
			self.indent += '  '
		elif c == ']':
			if not self.indent:
				raise ValueError
			self.indent = self.indent[:-2]
			if self.tokens[-1].mode == self.OPEN:
				del self.tokens[-1]
			else:
				self.tokens.append(Token(self.CLOSE, self.indent, 0))

def brainfuck_to_c(source_code):
	bf = BF(source_code)
	return bf.convert_to_c()


import re

def brainfuck_to_c(source_code):
	s = re.findall('[\\+-<>\\[\\]\\.,]+', source_code)
	s = ''.join(s)
	pattern = re.compile('<>|><|\\+-|-\\+|\\[\\]')
	while True:
		l = len(s)
		s = pattern.sub('', s)
		if l == len(s):
			break
	depth = 0
	for i in s:
		if i == '[':
			depth += 1
		if i == ']':
			depth -= 1
		if depth < 0:
			return 'Error!'
	if depth != 0:
		return 'Error!'
	s = re.findall('\\++|\\-+|<+|>+|\\.|,|\\[|\\]', s)
	for i in range(len(s)):
		if re.match('\\++', s[i]):
			s[i] = ' ' * depth + '*p += ' + str(len(s[i])) + ';\n'
		if re.match('-+', s[i]):
			s[i] = ' ' * depth + '*p -= ' + str(len(s[i])) + ';\n'
		if re.match('>+', s[i]):
			s[i] = ' ' * depth + 'p += ' + str(len(s[i])) + ';\n'
		if re.match('<+', s[i]):
			s[i] = ' ' * depth + 'p -= ' + str(len(s[i])) + ';\n'
		if re.match('\\.+', s[i]):
			s[i] = ' ' * depth + 'putchar(*p);\n'
		if re.match(',+', s[i]):
			s[i] = ' ' * depth + '*p = getchar();\n'
		if s[i] == '[':
			s[i] = ' ' * depth + 'if (*p) do {\n'
			depth += 2
		if s[i] == ']':
			depth -= 2
			s[i] = ' ' * depth + '} while (*p);\n'
	s = ''.join(s)
	return s


def brainfuck_to_c(s):
	s = ''.join([x for x in s if x in '+-><[].,'])
	rep = ['+-', '-+', '<>', '><', '[]']
	while sum([s.count(x) for x in rep]):
		for i in rep:
			s = s.replace(i, '')
	if len(s) == 0:
		return ''
	(t, r, shift) = ([s[0]], '', 0)
	for i in range(1, len(s)):
		if s[i] in t[-1] and s[i] in '+-<>':
			t[-1] += s[i]
		else:
			t += [s[i]]
	for i in t:
		if '+' in i:
			r += ' ' * 2 * shift + '*p += ' + str(len(i)) + ';\n'
		if '>' in i:
			r += ' ' * 2 * shift + 'p += ' + str(len(i)) + ';\n'
		if '-' in i:
			r += ' ' * 2 * shift + '*p -= ' + str(len(i)) + ';\n'
		if '<' in i:
			r += ' ' * 2 * shift + 'p -= ' + str(len(i)) + ';\n'
		if i == '.':
			r += ' ' * 2 * shift + 'putchar(*p);\n'
		if i == ',':
			r += ' ' * 2 * shift + '*p = getchar();\n'
		if i == ']':
			shift -= 1
			if shift < 0:
				return 'Error!'
			r += ' ' * 2 * shift + '} while (*p);\n'
		if i == '[':
			r += ' ' * 2 * shift + 'if (*p) do {\n'
			shift += 1
	return 'Error!' if shift > 0 else r