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);

Difficulty: interview

Starter code:

def brainfuck_to_c(source_code):
	

Solutions:
import re

def brainfuck_to_c(source):
    # remove comments
    source = re.sub('[^+-<>,.\[\]]', '', source)
    
    # remove redundant code
    before = ''
    while source != before:
        before = source
        source = re.sub('\+-|-\+|<>|><|\[\]', '', source)
    
    # check braces status
    braces = re.sub('[^\[\]]', '', source)
    while braces.count('[]'):
        braces = braces.replace('[]', '')
    if braces:
        return 'Error!'
    
    # split code into commands
    commands = re.findall('\++|-+|>+|<+|[.,\[\]]', source)
    
    # translate to C
    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(r'(\+\-)|(\-\+)|(<>)|(><)|(\[\])|[^+\-<>,.\[\]]','',sc)
  l,braces=-1,re.sub(r'[+\-.<>,]','',sc)
  while l!=len(braces): l=len(braces); braces=re.sub(r'(\[\])','',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(" | "),"""
- | *p -= %s;
+ | *p += %s;
< | p -= %s;
> | p += %s;
[ | if (*p) do {
] | } while (*p);
. | putchar(*p);
, | *p = getchar();
""".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(r'\[\]','', re.sub(r'<>|><','', re.sub(r'\+-|-\+','', re.sub(r'[^\+-<>,.\[\]]','',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