Esempio n. 1
0
def abc_xyz_simplified_with_gcd(prev_found_list, prev_total_cnt):

    new_list_no_reduced_1_1_2 =[]
    new_list_no_reduced_1_1_2_simplied = []

    for i in range(prev_total_cnt):

        find_item = prev_found_list[i]
        a = find_item[0]
        x = find_item[1]
        b = find_item[2]
        y = find_item[3]
        c = find_item[4]
        z = find_item[5]

        # get gcd for three number, a, b, c
        abc_gcd = gcd_for_three_numbers(a, b, c)

        output_str, is_reduced_to_1_1_2 = simplify(a, x, b, y, c, z, abc_gcd, print_option = True)

        # recuded form, 1 + 1 = 2 is the most common format, let's skip this type of solutions
        if(is_reduced_to_1_1_2 == False):

            tmp_arr = deepcopy(find_item)
            
            # record the item
            new_list_no_reduced_1_1_2.append(tmp_arr)
            
            # also record the "simplified string format"
            new_list_no_reduced_1_1_2_simplied.append(output_str)
            
    new_total_cnt = len(new_list_no_reduced_1_1_2)
    print '==before remove reduced_1_1_2, prev_total_cnt = %10d, after:  %10d ========================='%(prev_total_cnt,  new_total_cnt)

    return new_list_no_reduced_1_1_2, new_list_no_reduced_1_1_2_simplied,  new_total_cnt
Esempio n. 2
0
def abc_xyz(n, ab_search_range_start = 2, ab_search_range_end = 10, xy_power_range_start = 2, xy_power_range_end = 10, only_co_prime = 0, x_same_y = 0, abc_odd_option = 0):

    found_list = []
    find_item = [0]*6

    total_loop_cnt = 0

    global     skip_cnt_for_c_not_include_all_prime_factors_of_a_b

    if (xy_power_range_start > min_power_3):
        min_power = xy_power_range_start

    else:
        min_power = min_power_3

    for a in range(ab_search_range_start, ab_search_range_end):

        # if we are only interested in a, b, c are all odd
        if(abc_odd_option == 7) and (a%2 == 0):
            continue

        for x in range(min_power, xy_power_range_end):

            a_x = power_mod(a, x, n)

            # we only need to consider b>= a,
            # so that we will only count 3^3 + 6^3 = 3^5, not count
            # 6^3 + 3^3 = 3^5
            for b in range(a, ab_search_range_end):

                # if we are only interested in a, b, c are all odd
                if(abc_odd_option == 7) and (b%2 == 0):
                    continue

                # if we are interested in at least one of a, b is odd
                if(abc_odd_option == 1) and (a%2 == 0) and (b%2 != 1):
                    continue

                ab_gcd = gcd(a, b)

                for y in range(min_power, xy_power_range_end):
                        
                        # if x_same_y flag is set, we will only handle the case y = x
                        # In fact, it will be better if we just let y = x and not go into this 
                        # loop, but because y range is not much, so that will not be too much wasted.
                        if(x_same_y == 1) and (y != x):
                            continue
                            
                        b_y = power_mod(b, y, n)

                        # need a better algorithm to find a range for c
                        c_range = 6*(a + b)

                        for c in range(2, c_range):

                            # if we are only interested in a, b, c are all odd
                            if(abc_odd_option == 7) and (c%2 == 0):
                                continue

                            # skip obvious no-solution case
                            # if a, b has gcd factor (ab_gcd) which is larger than 1.
                            # and ab_gcd has prime factor p1, p2, ..pr
                            # then c must also contain those prime factors
                            if(ab_gcd > 1):

                                # Note: not sure if the following check will speed up program
                                # because it involve factoring a number, which can be slow.
                                # But if we have large z range, this will help.
                                # Plus, it will also reduce the memory to save initial list.
                                ret = check_c_contain_prime_factors_of_ab_gcd(ab_gcd, c)

                                # c does not contain all prime factors of ab_gcd,
                                # we need to skip this c.
                                if (ret == 0):
                                    skip_cnt_for_c_not_include_all_prime_factors_of_a_b += 1
                                    continue

                            # if only check co_prime, then, we will skip those numbers
                            # which are not co_primes
                            if(only_co_prime == 1):
                                abc_gcd = gcd_for_three_numbers(a, b, c)
                                
                                if(abc_gcd > 1):
                                    continue

                            # it can happen that z_start > z_end in case z_end = 2
                            # in this case, we just skip the z loop
                            z_start, z_end = get_range_for_z(a, x, b, y, c, min_power)

                            for z in range(z_start, z_end):
                                c_z = power_mod(c, z, n)

                                tmp = a_x + b_y - c_z

                                # found one, (tmp %n) == 0 is natural for mod(n)
                                if((tmp %n) == 0):

                                    # do additional filtering, this will reduce memory usage
                                    # needed for initial list saving.
                                    if(additional_filtering(tmp, initial_mod)):

                                        print 'a = %4d, x = %4d, b = %4d, y = %4d, c = %4d, z = %4d'%(a, x, b, y, c, z)

                                        find_item[0]=a
                                        find_item[1]=x
                                        find_item[2]=b
                                        find_item[3]=y
                                        find_item[4]=c
                                        find_item[5]=z

                                        tmp_arr = deepcopy(find_item)
                                        found_list.append(tmp_arr)
                                        # found_list.append(find_item)

                                total_loop_cnt += 1

    total_cnt = len(found_list)
    print '================== n = %5d, total_cnt = %10d ========================='%(n, total_cnt)

    return found_list, total_cnt, total_loop_cnt
Esempio n. 3
0
def simplify(a, x, b, y, c, z, abc_gcd, print_option = True):

    # 1 + 1 = 2 is the most common reduced format, we want to detect it
    is_reduced_to_1_1_2 = False

    # the following assertion is here because if it fail. It means that we find a solution
    # that its a, b, c are co-prime.
    assert (abc_gcd > 1)

    assert(a > 0)
    assert(b > 0)
    assert(c > 0)

    known_factor = abc_gcd

    # let's factor a^x = (u^v)*(r^s)
    ax_v, ax_r, ax_s = factor_power_of_num_with_known_factor(a, x, known_factor)
    by_v, by_r, by_s = factor_power_of_num_with_known_factor(b, y, known_factor)
    cz_v, cz_r, cz_s = factor_power_of_num_with_known_factor(c, z, known_factor)

    #print 'ax_v = %d, by_v = %d, cz_v = %d'%(ax_v, by_v, cz_v)

    # get the power of common factor for a^x, b^y, c^z
    common_factor_power = get_min(ax_v, by_v, cz_v)
    u = known_factor
    
    # after factoring out common_factor_power, u^common_factor_power, the remaining power factor of format u^?? for
    # a^x, b^y, c^z
    # For example, assume u = 2, a = (2^8)*(3^7), common_factor_power = 5, 
    # then after factoring out 2^5 from a^x, b^y, c^z, a will have remaining format (2^3)*(3^7 where 
    # ax_v_left = 3
    ax_v_left = ax_v - common_factor_power
    by_v_left = by_v - common_factor_power
    cz_v_left = cz_v - common_factor_power

    assert(ax_v_left >= 0)
    assert(by_v_left >= 0)
    assert(cz_v_left >= 0)

    # print 'a = %4d, x = %4d, b = %4d, y = %4d, c = %4d, z = %4d'%(a, x, b, y, c, z)
    # print 'u = %d common_factor_power = %d, ax_v_left = %d, by_v_left = %d, cz_v_left = %d'%(u, common_factor_power, ax_v_left, by_v_left, cz_v_left)

    #  after factoring out common factor power from a^x, b^y, c^z, 
    # for remaining part of each number,, output as (u^v)*(r^s) format. 
    # also try to detect if u or r == 1, or v and s == 0
    ax_u_v_r_s_str, ax_result_type = format_u_v_r_s_output(u, ax_v_left, ax_r, ax_s)
    by_u_v_r_s_str, by_result_type = format_u_v_r_s_output(u, by_v_left, by_r, by_s)
    cz_u_v_r_s_str, cz_result_type = format_u_v_r_s_output(u, cz_v_left, cz_r, cz_s)

    a_x_b_y_c_z_str = '%d^%d + %d^%d = %d^%d'%(a, x, b, y, c, z)
    output_str = '%24s  ==> %6s + %6s = %6s, u = %4d, cfp = %2d'%(a_x_b_y_c_z_str, ax_u_v_r_s_str, by_u_v_r_s_str,  cz_u_v_r_s_str, u, common_factor_power)

    # if the following condition meet, maybe, we can simplify it again in a recursive way
    if(          (ax_result_type == 1) or ( ax_result_type == 2 )) \
            and ((by_result_type == 1) or ( by_result_type == 2 )) \
            and ((cz_result_type == 1) or ( cz_result_type == 2)):

        # r^s for new a^x
        if(ax_result_type == 1):
            new_a = ax_r
            new_x = ax_s

        # u^v for new a^x
        if(ax_result_type == 2):
            new_a = u
            new_x = ax_v_left

        # r^s for new b^y
        if(by_result_type == 1):
            new_b = by_r
            new_y = by_s

        # u^v for new b^y
        if(by_result_type == 2):
            new_b = u
            new_y = by_v_left

        # r^s for new c^y
        if(cz_result_type == 1):
            new_c = cz_r
            new_z = cz_s

        # u^v for new c^y
        if(cz_result_type == 2):
            new_c = u
            new_z = cz_v_left

        new_gcd = gcd_for_three_numbers(new_a, new_b, new_c)

        if(new_gcd > 1):
            # the following is a recursive call, but will not print to screen
            output_str_again, is_reduced_to_1_1_2 = simplify(new_a, new_x, new_b, new_y, new_c, new_z, new_gcd, print_option = False)

        final_output_str = '%s --- %s '%(output_str, output_str_again)

    # this will not do recursive call
    else:
        final_output_str = '%s'%(output_str)

        # detect the most common reduced format: 1 + 1 = 2
        if(ax_result_type == 0) and (by_result_type == 0):
            is_reduced_to_1_1_2 = True

    if(print_option == True):
        print final_output_str

    return final_output_str, is_reduced_to_1_1_2