def tan_simplify(son1, son2):
    if son1.value == '0.0':
        return Node('0.0')
    if (son1.value == '/' and son1.son1.value == 'pi'
            and get_float_number_str_or_input_str(son1.son2.value) == '4.0'):
        return Node('1.0')
    return Node('tan', son1=son1)
def sin_simplify(son1, son2):
    if (son1.value == '/' and son1.son1.value == 'pi'
            and get_float_number_str_or_input_str(son1.son2.value) == '2.0'):
        return Node('1.0')
    if son1.value in ({'0.0'} | {'pi'}):
        return Node('0.0')
    return Node('sin', son1=son1)
def arcsin_simplify(son1, son2):
    if son1.value == '0.0':
        return Node('0.0')
    if son1.value == '1.0':
        return Node('pi/2', is_complex=True)
    if son1.value == '-1.0':
        return Node('3pi/2', is_complex=True)
    return Node('arcsin', son1=son1)
def unary_minus_simplify(son1, son2):
    if son1.value == '0.0':
        return Node('0')
    if is_number(son1.value):
        return Node(str(-float(son1.value)))
    cnt = 1
    while son1.value == 'neg':
        cnt += 1
        son1 = son1.son1
    return Node('neg', son1=son1, is_complex=True) if cnt % 2 != 0 else son1
def div_simplify(son1, son2):
    if is_number(son1.value) and is_number(son2.value):
        return Node(
            str(get_truncated_value(float(son1.value) / float(son2.value), 7)))
    if son2.value == '1.0':
        return son1
    if son1.value == '0.0':
        return Node('0.0')
    if son1.value == son2.value:
        return Node('1.0')
    return Node('/', son1=son1, son2=son2, is_complex=True)
def binary_plus_simplify(son1, son2):
    if is_number(son1.value) and is_number(son2.value):
        return Node(
            str(get_truncated_value(float(son1.value) + float(son2.value), 7)))
    if son1.value == '0.0':
        return son2
    if son2.value == '0.0':
        return son1
    return _deep_simplify_for_minus_and_plus('+', son1, son2)
def mult_simplify(son1, son2):
    if is_number(son1.value) and is_number(son2.value):
        return Node(
            str(get_truncated_value(float(son1.value) * float(son2.value), 7)))
    if son1.value == '0.0' or son2.value == '0.0':
        return Node('0')
    if son1.value == '1.0':
        return son2
    if son2.value == '1.0':
        return son1
    if son2.value == 'neg' and is_number(son1.value):
        return mult_simplify(
            Node(str(get_truncated_value(float(son1.value) * -1.0, 7))),
            son2.son1)
    if son1.value == 'neg' and is_number(son2.value):
        return mult_simplify(
            Node(str(get_truncated_value(float(son2.value) * -1.0, 7))),
            son1.son1)
    if (is_number(son1.value) and son2.value == '*'
            and is_number(son2.son1.value)):
        return mult_simplify(
            Node(
                str(
                    get_truncated_value(
                        float(son1.value) * float(son2.son1.value), 7))),
            son2.son2)
    if (is_number(son2.value) and son1.value == '*'
            and is_number(son1.son1.value)):
        return mult_simplify(
            Node(
                str(
                    get_truncated_value(
                        float(son2.value) * float(son1.son1.value), 7))))
    if son1.value == '-1.0':
        return Node('neg', son2)
    if is_number(son2.value):
        return Node('*', son1=son2, son2=son1, is_complex=True)
    return Node('*', son1=son1, son2=son2, is_complex=True)
def arctan_simplify(son1, son2):
    if son1.value == '0.0':
        return Node('0.0')
    if son1.value == '1.0':
        return Node('pi/4', is_complex=True)
    return Node('arctan', son1=son1)
def ln_simplify(son1, son2):
    if son1.value == 'e':
        return Node('1.0')
    return Node('ln', son1=son1)
def lg_simplify(son1, son2):
    if son1.value == '10.0':
        return Node('1.0')
    return Node('lg', son1=son1)
def _deep_simplify_for_minus_and_plus(operation, son1, son2):
    bfs_arr = [(son1, 0)]
    if operation == '-':
        bfs_arr.append((son2, 1))
    else:
        bfs_arr.append((son2, 0))
    nodes_to_sum = []
    n = 2
    i = 0
    while i < n:
        cur_node = bfs_arr[i][0]
        cur_sign = bfs_arr[i][1]
        if not is_operator(cur_node.value) and not cur_node.is_complex:
            nodes_to_sum.append((cur_node, cur_sign))
        elif cur_node.value != '+' and cur_node.value != '-':
            if cur_node.value == 'neg':
                cur_sign += 1
            nodes_to_sum.append((cur_node, cur_sign))
        else:
            bfs_arr.append((cur_node.son1, cur_sign))
            if cur_node.value == '-':
                bfs_arr.append((cur_node.son2, cur_sign + 1))
            else:
                bfs_arr.append((cur_node.son2, cur_sign))
            n += 2
        i += 1
    res_node = None
    plus_dict = {'number': 0.0}
    for cur_tuple in nodes_to_sum:
        cur_node = cur_tuple[0]
        cur_sign = float(pow(-1, cur_tuple[1]))
        if (cur_node.value == '*' and (is_number(cur_node.son1.value)
                                       and not is_number(cur_node.son2.value)
                                       and not is_operator(cur_node.son2.value)
                                       and not cur_node.son2.is_complex)):
            coef = float(cur_node.son1.value) * cur_sign
            if cur_node.son2.value in plus_dict.keys():
                plus_dict[cur_node.son2.value] += coef
            else:
                plus_dict[cur_node.son2.value] = coef
        elif not is_operator(cur_node.value) and not cur_node.is_complex:
            if is_number(cur_node.value):
                plus_dict['number'] = get_truncated_value(
                    plus_dict['number'] + float(cur_node.value) * cur_sign, 7)
            elif cur_node.value in plus_dict.keys():
                plus_dict[cur_node.value] += cur_sign
            else:
                plus_dict[cur_node.value] = cur_sign
        else:
            if cur_node.value == 'neg':
                cur_node = cur_node.son1
            if res_node is None:
                if cur_sign < 0:
                    res_node = Node('neg', cur_node)
                else:
                    res_node = cur_node
            else:
                if cur_sign < 0:
                    res_node = Node('-',
                                    son1=res_node,
                                    son2=cur_node,
                                    is_complex=True)
                else:
                    res_node = Node('+',
                                    son1=res_node,
                                    son2=cur_node,
                                    is_complex=True)
    if plus_dict['number'] != 0.0:
        if res_node is not None:
            if plus_dict['number'] < 0:
                res_node = Node('-', res_node, Node(str(-plus_dict['number'])))
            else:
                res_node = Node('+', res_node, Node(str(plus_dict['number'])))
        else:
            res_node = Node(str(plus_dict['number']))
    for x in plus_dict.keys():
        if x != 'number':
            if res_node is not None:
                if plus_dict[x] < 0:
                    res_node = Node(
                        '-', res_node,
                        mult_simplify(Node(str(-plus_dict[x])), Node(x)))
                else:
                    res_node = Node(
                        '+', res_node,
                        mult_simplify(Node(str(plus_dict[x])), Node(x)))
            else:
                if plus_dict[x] < 0:
                    res_node = Node(
                        'neg', mult_simplify(Node(str(plus_dict[x])), Node(x)))
                else:
                    res_node = mult_simplify(Node(str(plus_dict[x])), Node(x))
    res_node.is_complex = True
    return res_node
def pow_simplify(son1, son2):
    if son2.value == '0.0' or son1.value == '1.0':
        return Node('1.0')
    if son2.value == '1.0':
        return son1
    return Node('^', son1=son1, son2=son2, is_complex=True)