human
Complete this python program:
def factor_nc(expr):
assistant
#Here is the Python code you requested.

    """Return the factored form of ``expr`` while handling non-commutative
    expressions.
    Examples
    >>> from sympy.core.exprtools import factor_nc
    >>> from sympy import Symbol
    >>> from sympy.abc import x
    >>> A = Symbol(\A\, commutative=False)
    >>> B = Symbol(\B\, commutative=False)
    >>> factor_nc((x**2 + 2*A*x + A**2).expand())
    (x + A)**2
    >>> factor_nc(((x + A)*(x + B)).expand())
    (x + A)*(x + B)
    """
    from sympy.simplify.simplify import powsimp
    from sympy.polys import gcd, factor
    def _pemexpand(expr):
        'Expand    with    the    minimal    set    of    hints    necessary    to    check    the    result.'
        return expr.expand(deep=True, mul=True, power_exp=True, power_base=False, basic=False, multinomial=True, log=False)
    expr = sympify(expr)
    if ((not isinstance(expr, Expr)) or (not expr.args)):
        return expr
    if (not expr.is_Add):
        return expr.func(*[factor_nc(a) for a in expr.args])
    (expr, rep, nc_symbols) = _mask_nc(expr)
    if rep:
        return factor(expr).subs(rep)
    else:
        args = [a.args_cnc() for a in Add.make_args(expr)]
        c = g = l = r = S.One
        hit = False
        for (i, a) in enumerate(args):
            if (i == 0):
                c = Mul._from_args(a[0])
            elif a[0]:
                c = gcd(c, Mul._from_args(a[0]))
            else:
                c = S.One
        if (c is not S.One):
            hit = True
            (c, g) = c.as_coeff_Mul()
            if (g is not S.One):
                for (i, (cc, _)) in enumerate(args):
                    cc = list(Mul.make_args((Mul._from_args(list(cc)) / g)))
                    args[i][0] = cc
            for (i, (cc, _)) in enumerate(args):
                cc[0] = (cc[0] / c)
                args[i][0] = cc
        for (i, a) in enumerate(args):
            if (i == 0):
                n = a[1][:]
            else:
                n = common_prefix(n, a[1])
            if (not n):
                if (not args[0][1]):
                    break
                (b, e) = args[0][1][0].as_base_exp()
                ok = False
                if e.is_Integer:
                    for t in args:
                        if (not t[1]):
                            break
                        (bt, et) = t[1][0].as_base_exp()
                        if (et.is_Integer and (bt == b)):
                            e = min(e, et)
                        else:
               ...