Search code examples
javaartificial-intelligencecryptarithmetic-puzzle

Solving this cryptarithmetic program gives infinite results


I am doing the EAT+ THAT= APPLE, where each letter represents a different number from 0-9. I need to find all combinations. I was wondering if there is a better way to write it, especially 'if' and 'for'

I've tried writing it like this but it gave me infinite results

public class Main {


public static void main(String[] args) {
int count = 0;
int E,A,T,P,L,H;

for (E = 0; E <=9; E++)   
{
    for (A = 0; A <=9; A++)
        for (T = 0; T <=9; T++)
            for (P = 0; P <=9; P++)
                for (L = 0; L <=9; L++)
                    for (H = 0; H <=9; H++)

    if (((E != A) && (E != L) && (E != T)&&(E !=P) &&(E!=L)&&(E!=H) && 
            (T != A) && (T != L) && (T != E) &&(T!=P)&&(T!=L)&&(T!=H)))
    {
        System.out.println("A"+A+"P"+P+"P"+P+"L"+L+"E"+E);

    }
    else count = count +1;    
}
System.out.println(count);

    }
}

Solution

  • When facing such problems it is of great importance to simplify the problem as much as possible.

    Let's create a sub problem:

    Assume that THAT must equal 8208. What are the values of each character?

    You can notice that you are just solving an equation: T * 1000 + H * 100 + A * 10 + T = 8208 (The only solution is T = 8, H = 2, A = 0)

    Back to our main problem:

    Using the logic above simplify the main problem to an equation,

    EAT + THAT= APPLE => EAT + THAT - APPLE = 0;

    That in fact means:

    E * 100 + A * 10 + T + T * 1000 + H * 100 + A * 10 + T - A * 10000 - P * 1000 - P * 1000 - L * 10 - E = 0

    After simplification you get: -9980 * A - 1100 * P + 1002 * T + 100 * H + 99 * E - 10 * L = 0

    As the values for each variable are very limited we are free to brute force the solution.

    public class MyClass {
       public static int[] calc(){
          for(int A = 0; A < 10; A++){
              for(int P = 0; P < 10; P++){
                  for(int T = 0; T < 10; T++){
                      for(int H = 0; H < 10; H++){
                          for(int E = 0; E < 10; E++){
                              for(int L = 0; L < 10; L++){
                                  if(A!=P && A != T && A != H && A != E && A != L && P != T && P != H && P != E && P != L && T != H && T != E && T != L && H != E && H != L && E != L){
                                     //In your code you are lacking this statment, it checks whether values are indeed a solution of the equation
                                     if(-9980 * A - 1100 * P + 1002 * T + 100 * H + 99 * E - 10 * L == 0){
                                         int[] outArr = {A, P, T, H, E, L};
                                         return outArr;
                                     }
                                  }
                              }
                          }
                      }
                  }
               }
           }
           return null;
       }
        
       public static void main(String args[]) {
         int[] answer = calc();
         System.out.println("A" + answer[0] + " P" + answer[1] + " P" + answer[1] + " L" + answer[5] + " E" + answer[4]);
       }
    }
    

    If you don't want your if statement to be this massive, you can always create an array of size 10 filled with zeroes and for each variable (let's call it i) increase the value for the given index with array[i]++;, if at any point at any index array[x] > 1 you will know that values repeat.

    There are ways of optimizing how the script works, by acknowledging the relations between digits (for example you can observe that A can only equal either 0 or 1, whereas 0 leads up to a contradictory equation, so A must equal 1 and so on and so forth until you find the exact value for each digit just by using logic), but in the end you will end up with purely mathematical solution and I don't think that's what you want to end up with.