def try_all_beals(lim=1000):
    
    populate_all()
    
    #b is in the primes since composite moduli don't have primitve roots.  Techincally, b could be in the prime powers or 2p^k, but the first is redundant for this application while the second isn't satisfied since b must be a power greater than two
    for b in prob_primes:
        
        print(b)        
        b_gp = get_gen_psq(b)
        
        for a in range(3, lim):
            if is_gen_n_k(a, b, all_fact[b]):            
                for c in range(3, lim):
                    if odd_num_evens(a, b, c) and is_coprime(a, c) and is_coprime(b, c):
                        for z in range(3, lim):
                            r = beals_solver(a, b, c, z, b_gp)
                            
                            #print(a, b, c, z)
                            
                            if r[2][0]:
                                if r[0] > 2 and r[1] > 2:
                                    print("\t!!!!{!s}^{!s} {} {!s}^{!s} = {!s}^{!s}!!!!".format(a, r[0], r[2][1], b, r[1], c, z))
                                    #wait = input("\tPossible solution found.  Press enter to continue.")
                                elif r[0] > 1 and r[1] > 1 and max(r[0], r[1]) > 2:
                                    print("\t{!s}^{!s} {} {!s}^{!s} = {!s}^{!s}".format(a, r[0], r[2][1], b, r[1], c, z))
def get_y(a, x, c, z, b, lrab, max_yc, b_gp):
    
    y_res_mod = []
    
    max_ya = x * lrab
    max_y = max(max_ya, max_yc)
    
    p = 1
    
    for pprime, pprime_sq, prime_sq_tot, prime_div in b_gp:
        #squared prime modulus ensures totient is divisible by prime
        ax, cz = exp_bs(a, x, pprime_sq), exp_bs(c, z, pprime_sq)
        
        d = (ax - cz) % pprime_sq
        
        if is_coprime(d, pprime_sq):                
            y_sp = dlog_mod(b, d, pprime_sq, prime_sq_tot, prime_div)
            y_res_mod.append([y_sp, pprime])
            
            p *= pprime
            
            if p > max_y:
                break
    else:
        print("Not enough primes to get y")
        #raise Error("Not enough primes to get y")
    
    return crt(y_res_mod)
def prob_beals(min_xyz=3, min_abc=2):
    
    populate_pprimes_list()
    
    #minimum sum is x+y+z=3+3+3=9 and a+b+c=2+3+5=10
    s = 19
    
    while True:
        #print("Shell with sum {!s} completed!".format(s))
        
        for a in range(min_abc, s + 1):
            s_1 = s - a
            
            for b in range(min_abc, s_1 + 1):
                s_2 = s_1 - b
                
                if b > a and is_coprime(a, b):         
                    
                    for c in range(min_abc, s_2 + 1):
                        s_3 = s_2 - c
                        
                        if is_coprime(a, c) and is_coprime(b, c):               
                            
                            for x in range(min_xyz, s_3 + 1):
                                s_4 = s_3 - x
                                
                                for y in range(min_xyz, s_4 + 1):
                                    z = s_4 - y
                                    
                                    if z >= min_xyz:
                                    
                                        for p in prob_primes:
                                            
                                            p_tot = p - 1
                                            
                                            a_m, b_m, c_m = a % p, b % p, c % p
                                            x_m, y_m, z_m = x % p_tot, y % p_tot, z % p_tot
                                            
                                            a_x, b_y, c_z = exp_bs(a, x, p), exp_bs(b, y, p), exp_bs(c, z, p)
                                            
                                            if (a_x + b_y) % p != c_z:
                                                break
                                        else:
                                            print("{!s}^{!s} + {!s}^{!s} = {!s}^{!s}".format(a, x, b, y, c, z))
                                        
        s += 1
def get_y(a, x, c, z, b, lrab, max_yc):
    
    y_res_mod = []
    
    max_ya = x * lrab
    max_y = max(max_ya, max_yc)
    
    p = 1
    mr = MontgomeryReduction()
    
    for i, pprime in enumerate(prob_primes):
        if is_gen_n_k(b, pprime, all_fact[pprime]): 
            m = pprime**2
            
            #squaring ensures totient is divisible by prime
            mr.set_modulus(m, prime_sq_fact[i])
                    
            ra, rc, rb = mr.convert(a), mr.convert(c), mr.convert(b)
            rax, rcz = mr.exp(ra, x), mr.exp(rc, z)
            
            rd = (rax - rcz) % m
            
            if is_coprime(rd, m):                
                y_sp = mr.dlog_mod(rb, rd, [pprime, 1])
                y_res_mod.append([y_sp, pprime])
                
                p *= pprime
                
                if p > max_y:
                    break
    else:
        ipdb.set_trace()
        print("Not enough primes to get y")
        #raise Error("Not enough primes to get y")
    
    return crt(y_res_mod)