r"""
    Standardizes a boolean expression into an or-ing of and-ed variables

    Args:
        boolexpr_ (str):

    Returns:
        str: final_expr

    CommandLine:
        sudo pip install git+https://github.com/tpircher/quine-mccluskey.git
        python -m utool.util_alg standardize_boolexpr --show

    Example:
        >>> # DISABLE_DOCTEST
        >>> from utool.util_alg import *  # NOQA
        >>> import utool as ut
        >>> boolexpr_ = 'not force_opencv and (orient_ or is_gif)'
        >>> result = standardize_boolexpr(boolexpr_, parens=True)
        >>> print(result)
        (orient_ and (not force_opencv)) or (is_gif and (not force_opencv))

def standardize_boolexpr(boolexpr_, parens=False):
    r"""
    Standardizes a boolean expression into an or-ing of and-ed variables

    Args:
        boolexpr_ (str):

    Returns:
        str: final_expr

    CommandLine:
        sudo pip install git+https://github.com/tpircher/quine-mccluskey.git
        python -m utool.util_alg standardize_boolexpr --show

    Example:
        >>> # DISABLE_DOCTEST
        >>> from utool.util_alg import *  # NOQA
        >>> import utool as ut
        >>> boolexpr_ = 'not force_opencv and (orient_ or is_gif)'
        >>> result = standardize_boolexpr(boolexpr_, parens=True)
        >>> print(result)
        (orient_ and (not force_opencv)) or (is_gif and (not force_opencv))
    """
    import utool as ut
    import re
    onlyvars = boolexpr_
    onlyvars = re.sub('\\bnot\\b', '', onlyvars)
    onlyvars = re.sub('\\band\\b', '', onlyvars)
    onlyvars = re.sub('\\bor\\b', '', onlyvars)
    onlyvars = re.sub('\\(', '', onlyvars)
    onlyvars = re.sub('\\)', '', onlyvars)
    varnames = ut.remove_doublspaces(onlyvars).strip().split(' ')
    varied_dict = {var: [True, False] for var in varnames}
    bool_states = ut.all_dict_combinations(varied_dict)
    outputs = [eval(boolexpr_, state.copy(), state.copy()) for state in bool_states]
    true_states = ut.compress(bool_states, outputs)
    true_tuples = ut.take_column(true_states, varnames)
    true_cases = [str(''.join([str(int(t)) for t in tup])) for tup in true_tuples]

    # Convert to binary
    ones_bin = [int(x, 2) for x in true_cases]
    #ones_str = [str(x) for x in true_cases]
    from quine_mccluskey.qm import QuineMcCluskey
    qm = QuineMcCluskey()
    result = qm.simplify(ones=ones_bin, num_bits=len(varnames))
    #result = qm.simplify_los(ones=ones_str, num_bits=len(varnames))

    grouped_terms = [dict(ut.group_items(varnames, rs)) for rs in result]
    def parenjoin(char, list_):
        if len(list_) == 0:
            return ''
        else:
            if parens:
                return '(' + char.join(list_) + ')'
            else:
                return char.join(list_)

    if parens:
        expanded_terms = [
            (
                term.get('1', []) +
                ['(not ' + b + ')' for b in term.get('0', [])] +
                [
                    parenjoin(' ^ ', term.get('^', [])),
                    parenjoin(' ~ ', term.get('~', [])),
                ]
            ) for term in grouped_terms
        ]
    else:
        expanded_terms = [
            (
                term.get('1', []) +
                ['not ' + b  for b in term.get('0', [])] +
                [
                    parenjoin(' ^ ', term.get('^', [])),
                    parenjoin(' ~ ', term.get('~', [])),
                ]
            ) for term in grouped_terms
        ]

    final_terms = [[t for t in term if t] for term in expanded_terms]

    products = [parenjoin(' and ', [f for f in form if f]) for form in final_terms]
    final_expr = ' or '.join(products)
    return final_expr