Search code examples
cryptarithmetic-puzzle

Simple cryptographic puzzle


I'm looking for a way to solve this crypt arithmetic problem of:

ROBERT +  GERALD =  DONALD

and potentially others as well, where each letter represents a digit.

How would you go about solving this by hand and how does that relate to solving it programmatically?

Thank you in advance


Solution

  • You can actually work this out as a sum:

      robert
    + gerald
      ------
    = donald
    

    and use basic mathematical knowledge.

    For example, there's no carry possible in the right column (6) and we have T + D = D. That means T must be zero.

    Similarly, for column 5, there's no carry from column 6 and R + L = L means R is zero as well, and no carry to column 4.

    Same with column 4, E + A = A so E is zero.

    So we now have:

      0ob000
    + g00ald
      ------
    = donald
    

    From there, we can infer from columns 3 and 1 that b==n and g==d and they (along with o/a/l/d) can be any value since every digit is being added to zero so there is no chance of carry anywhere. So let's just make them all one:

      011000
    + 100111
      ------
    = 111111
    

    In fact, you could make them all zero and end up with 000000 + 000000 = 000000.

    But that's hardly programming related, so let's make it so:

    #include <stdio.h>
    int main (void) {
     int robert, gerald, donald;
     for (int r = 0; r < 10; r++) {
      for (int o = 0; o < 10; o++) {
       for (int b = 0; b < 10; b++) {
        for (int e = 0; e < 10; e++) {
         for (int t = 0; t < 10; t++) {
          for (int g = 0; g < 10; g++) {
           for (int a = 0; a < 10; a++) {
            for (int l = 0; l < 10; l++) {
             for (int d = 0; d < 10; d++) {
              for (int n = 0; n < 10; n++) {
               robert = r * 100000 + o * 10000 + b * 1000 + e * 100 + r * 10 + t;
               gerald = g * 100000 + e * 10000 + r * 1000 + a * 100 + l * 10 + d;
               donald = d * 100000 + o * 10000 + n * 1000 + a * 100 + l * 10 + d;
               if (robert + gerald == donald) {
                printf ("  %06d\n", robert);
                printf ("+ %06d\n", gerald);
                printf ("  ------\n");
                printf ("= %06d\n", donald);
                printf ("........\n");
               }
              }
             }
            }
           }
          }
         }
        }
       }
      }
     }
     return 0;
    }
    

    That will give you a whole host of solutions.

    And, before you complain that you cannot have repeated digits, there is no solution if that's the case, since mathematically both T and R must be zero, as shown in the original reasoning above. And you can prove this empirically with:

    #include <stdio.h>
    int main (void) {
     int robert, gerald, donald;
     for (int r = 0; r < 10; r++) {
      for (int o = 0; o < 10; o++) {
       if (o==r) continue;
       for (int b = 0; b < 10; b++) {
        if ((b==r) || (b==o)) continue;
        for (int e = 0; e < 10; e++) {
         if ((e==r) || (e==o) || (e==b)) continue;
         for (int t = 0; t < 10; t++) {
          if ((t==r) || (t==o) || (t==b) || (t==e)) continue;
          for (int g = 0; g < 10; g++) {
           if ((g==r) || (g==o) || (g==b) || (g==e) || (g==t)) continue;
           for (int a = 0; a < 10; a++) {
            if ((a==r) || (a==o) || (a==b) || (a==e) || (a==t) || (a==g)) continue;
            for (int l = 0; l < 10; l++) {
             if ((l==r) || (l==o) || (l==b) || (l==e) || (l==t) || (l==g) || (l==a)) continue;
             for (int d = 0; d < 10; d++) {
              if ((d==r) || (d==o) || (d==b) || (d==e) || (d==t) || (d==g) || (d==a) || (d==l)) continue;
              for (int n = 0; n < 10; n++) {
               if ((n==r) || (n==o) || (n==b) || (n==e) || (n==t) || (n==g) || (n==a) || (n==l) || (n==d)) continue;
               robert = r * 100000 + o * 10000 + b * 1000 + e * 100 + r * 10 + t;
               gerald = g * 100000 + e * 10000 + r * 1000 + a * 100 + l * 10 + d;
               donald = d * 100000 + o * 10000 + n * 1000 + a * 100 + l * 10 + d;
               if (robert + gerald == donald) {
                printf ("  %06d\n", robert);
                printf ("+ %06d\n", gerald);
                printf ("  ------\n");
                printf ("= %06d\n", donald);
                printf ("........\n");
               }
              }
             }
            }
           }
          }
         }
        }
       }
      }
     }
     return 0;
    }
    

    which outputs no solutions.

    Now DONALD + GERALD = ROBERT, that's a different matter but you can solve that simply by modifying the code above slightly, making the if statement into:

    if (donald + gerald == robert) {
     printf ("  %06d\n", donald);
     printf ("+ %06d\n", gerald);
     printf ("  ------\n");
     printf ("= %06d\n", robert);
     printf ("........\n");
    }
    

    and you get the single solution:

      526485
    + 197485
      ------
    = 723970