Search code examples
pythonoptimization

Make code faster to solve which letter represents which digit in a given equation


I am going to do a math competition which allows writing programs to solve problems.

The code attempts to solve this problem:

WHITE+WATER=PICNIC where each distinct letter represents a different digit. Find the number represented by PICNIC.

No imports are allowed (tqdm was just a progress bar). What I tried is below. At the rate of which my computer goes, it is not fast enough for the times competition because it needs to range over 10 to the power of digits there is.

Is there a clear solution to this problem?

from tqdm import tqdm

def find_solution():
    for W in tqdm(range(10)):
        for H in tqdm(range(10), desc='H'):
            for I in tqdm(range(10), desc='I'):
                for T in tqdm(range(10)):
                    for E in tqdm(range(10)):
                        for A in (range(10)):
                            for R in (range(10)):
                                for P in (range(1, 10)): # P cannot be 0
                                    for C in (range(10)):
                                        for N in (range(10)):
                                            white = W * 10000 + H * 1000 + I * 100 + T * 10 + E
                                            water = W * 10000 + A * 1000 + T * 100 + E * 10 + R
                                            picnic = P * 100000 + I * 10000 + C * 1000 + N * 100 + I * 10 + C

                                            if white + water == picnic:
                                                return {'W': W, 'H': H, 'I': I, 'T': T, 'E': E, 'A': A, 'R': R, 'P': P, 'C': C, 'N': N}

    return None

solution = find_solution()

if solution:
    print("Solution found:")
    print(solution)
else:
    print("No solution found.")

Solution

  • Observations:

    1. P=1 due to a carry to its sixth digit
    2. W must be 5-9 due to a carry being generated (1)
    3. No letter can be the same value as another letter.
    def find_solution():
        P = 1
        for W in range(5,10):
            for H in range(10):
                if H in (P,W): continue
                for I in range(10):
                    if I in (H,P,W): continue
                    for T in range(10):
                        if T in (I,H,P,W): continue
                        for E in range(10):
                            if E in (T,I,H,P,W): continue
                            for A in range(10):
                                if A in (E,T,I,H,P,W): continue
                                for R in range(10):
                                    if R in (A,E,T,I,H,P,W): continue
                                    for C in range(10):
                                        if C in (R,A,E,T,I,H,P,W): continue
                                        for N in range(10):
                                            if N in (C,R,A,E,T,I,H,P,W): continue
                                            white = W * 10000 + H * 1000 + I * 100 + T * 10 + E
                                            water = W * 10000 + A * 1000 + T * 100 + E * 10 + R
                                            picnic = P * 100000 + I * 10000 + C * 1000 + N * 100 + I * 10 + C
    
                                            if white + water == picnic:
                                                print(f' WHITE= {white}')
                                                print(f' WATER= {water}')
                                                print(f'PICNIC={picnic}')
                                                print()
    
    find_solution()
    

    Output (2 solutions, ~1 second):

     WHITE= 83642
     WATER= 85427
    PICNIC=169069
    
     WHITE= 85642
     WATER= 83427
    PICNIC=169069
    

    Faster, of course, if you can use libraries (~0.3 sec). Note the documentation of itertools.permutations has a rough Python-only implementation, but it is slower than the hard-coded version above:

    from itertools import permutations
    
    def find_solution():
        P=1
        for W,H,I,T,E,A,R,C,N in permutations([0,2,3,4,5,6,7,8,9]):
            if W < 5: continue
            white = W * 10000 + H * 1000 + I * 100 + T * 10 + E
            water = W * 10000 + A * 1000 + T * 100 + E * 10 + R
            picnic = P * 100000 + I * 10000 + C * 1000 + N * 100 + I * 10 + C
    
            if white + water == picnic:
                print(f' WHITE= {white}')
                print(f' WATER= {water}')
                print(f'PICNIC={picnic}')
                print()
    
    find_solution()