To almost all of us solving sets of linear equations is quite obviously the most exciting bit of linear algebra. Benny does not agree though and wants to write a quick program to solve his homework problems for him. Unfortunately Benny's lack of interest in linear algebra means he has no real clue on how to go about this. Fortunately, you can help him!
Write a method ```solve``` that accepts a list of linear equations that your method will have to solve. The output should be a map (a `Map` object in JavaScript) with a value for each variable in the equations. If the system does not have a unique solution (has infinitely many solutions or is unsolvable), return ```null``` (`None` in python).
For example :  
"2x + 4y + 6z = 18"  
"3y + 3z = 6"  
"x + 2y = z - 3"
should result in a map :  
x = 2  
y = -1  
z = 3  
Possible input equations have the following rules:  
-   Only the plus and minus operators are used on both the left and right hand side of the equation.  
-   Both sides of the equation can have variables; One variable can appear in multiple terms, on both sides.
-   Variable names are strings of arbitrary length.  
-   All coefficients are integers and generally fall within the range of -150 to 150, with a few ranging from -1000 to 1000. Free terms are integers in range -20000 to 20000.  
-   Equations do not necessarily have variables.  
-   Equations have exactly one operator (+ or -) between terms.  
Comparisons are performed with accuracy of `1e-6`.
**Note on numerical stability:**
There are many possible ways to solve a system of linear equations. One group of such algorithms is based on reduction and elimination methods. If you are going to use any of these, remember that such algorithms are in general *numerically unstable*, i.e. division operations repeated over and over introduce inaccuracies which accumulate from row to row. As a result it might occur that some value which is expected to be zero is actually larger, for example, `2.5e-10`. Such inaccuracies tend to be bigger in large equation systems, and random tests check systems of up to 26 equations. If it happens that small tests pass for you, and large tests fail, it probably means that you did not account for inaccuracies correctly.
Also note that tests do not depend on any reference solution, so the way how test cases are generated _is numrically stable_ - the only source of inaccuracies is your solution, and you need to account for it.
```if:python
___Note for python users:___
`numpy` module has been disabled, so that the task matches the one of the other languages. There is an anti-cheat measure about that, so you won't be able to import some other modules too (either way, you shouldn't need any module to solve this kata...)
```
def decode_eq_side(eq_side):
    result = {}
    sign, factor, var_name = 1, "", ""

    def add_variable():
        nonlocal factor, var_name, result
        if var_name:
            result[var_name] = result.get(var_name, 0) + sign * int(factor) if factor else result.get(var_name, 0) + sign
        elif factor:
            result[""] = result.get(var_name, 0) + sign * int(factor) if factor else result.get(var_name, 0) + sign
        factor, var_name = "", ""

    for i, s in enumerate(eq_side.replace(" ", "")):
        if s == "+":
            add_variable()
            sign = 1
        elif s == "-":
            add_variable()
            sign = -1
        elif s.isdigit():
            factor += s
        else:
            var_name += s
    else:
        add_variable()
    return result


def decode_equation(equation):
    variables, variables2 = [decode_eq_side(side) for side in equation.split("=")]
    for var, factor in variables2.items():
        variables[var] = variables.get(var, 0) - factor
    variables[""] = -1*variables.get("", 0)
    return variables


def solve(*equations):
    # get equation variables and matrix
    equations_variables = [decode_equation(equation) for equation in equations]
    variable_names = {var_name for eq_vars in equations_variables for var_name in eq_vars}
    variable_names.discard("")
    variable_names = list(variable_names)
    if len(variable_names) > len(equations_variables):
        return None
    equations_matrix = [[variables.get(var_name, 0) for var_name in variable_names] + [variables.get("", 0)] for variables in equations_variables]
    del equations_variables
    # gauss elimination
    gauss_matrix = []
    for i in range(len(variable_names)):
        chosen_row = max(equations_matrix, key=lambda row: abs(row[i]))
        # check if solution is indeterminate
        if abs(chosen_row[i]) < 1e-10:
            return None
        equations_matrix.remove(chosen_row)
        gauss_matrix.append([0]*i + [param/chosen_row[i] for param in chosen_row[i:]])
        for row_i, row in enumerate(equations_matrix):
            equations_matrix[row_i] = [0]*(i+1) + [param - row[i]*gauss_matrix[-1][i+j+1] for j, param in enumerate(row[i+1:])]
    # check if there are no solution
    if any(abs(row[-1]) > 1e-10 for row in equations_matrix):
        return None
    solution = []
    for equation in reversed(gauss_matrix):
        solution.append(equation[-1] - sum([equation[-(2+i)]*param for i, param in enumerate(solution)]))
    return dict(zip(variable_names, reversed(solution)))
def decode_eq_side(eq_side):
    result = {}
    sign, factor, var_name = 1, "", ""

    def add_variable():
        nonlocal factor, var_name, result
        if var_name:
            result[var_name] = result.get(var_name, 0) + sign * int(factor) if factor else result.get(var_name, 0) + sign
        elif factor:
            result[""] = result.get(var_name, 0) + sign * int(factor) if factor else result.get(var_name, 0) + sign
        factor, var_name = "", ""

    for i, s in enumerate(eq_side.replace(" ", "")):
        if s == "+":
            add_variable()
            sign = 1
        elif s == "-":
            add_variable()
            sign = -1
        elif s.isdigit():
            factor += s
        else:
            var_name += s
    else:
        add_variable()
    return result


def decode_equation(equation):
    variables, variables2 = [decode_eq_side(side) for side in equation.split("=")]
    for var, factor in variables2.items():
        variables[var] = variables.get(var, 0) - factor
    variables[""] = -1*variables.get("", 0)
    return variables


def solve(*equations):
    # get equation variables and matrix
    equations_variables = [decode_equation(equation) for equation in equations]
    variable_names = {var_name for eq_vars in equations_variables for var_name in eq_vars}
    variable_names.discard("")
    variable_names = list(variable_names)
    if len(variable_names) > len(equations_variables):
        return None
    equations_matrix = [[variables.get(var_name, 0) for var_name in variable_names] + [variables.get("", 0)] for variables in equations_variables]
    del equations_variables
    # gauss elimination
    gauss_matrix = []
    for i in range(len(variable_names)):
        chosen_row = max(equations_matrix, key=lambda row: abs(row[i]))
        # check if solution is indeterminate
        if abs(chosen_row[i]) < 1e-10:
            return None
        equations_matrix.remove(chosen_row)
        gauss_matrix.append([0]*i + [param/chosen_row[i] for param in chosen_row[i:]])
        for row_i, row in enumerate(equations_matrix):
            equations_matrix[row_i] = [0]*(i+1) + [param - row[i]*gauss_matrix[-1][i+j+1] for j, param in enumerate(row[i+1:])]
    # check if there are no solution
    if any(abs(row[-1]) > 1e-10 for row in equations_matrix):
        return None
    solution = []
    for equation in reversed(gauss_matrix):
        solution.append(equation[-1] - sum([equation[-(2+i)]*param for i, param in enumerate(solution)]))
    return dict(zip(variable_names, reversed(solution)))