I'm trying to solve a cryptarithmetic puzzle TOO + TOO + TOO + TOO = GOOD using a program.

My solution to this, is to use a nested loop for each unique letter (in this case T, O, G, D). The loops would systematically assign the digits from 0-9 to each letter. For example, it might first try T = 0, O = 0, G = 0, D = 0, then T = 0, O = 0, G =0, D = 1, then T = 0, O = 0, G = 0, D = 2, etc. up to T = 9, O = 9, G = 9, D = 9.

Would this be the correct way to do this? If it is, the answer I got using my program was 1642 which I know isn't correct considering there's only 3 values instead of 4 (TOO)

Dani AI

Generated

Nice idea, . Brute force works as said, but you can cut the search to almost nothing by using the column-wise carries from the start. For TOO+TOO+TOO+TOO=GOOD the carries give you these constraints before you ever try T or G:

  • ones: 4O = D + 10c1
  • tens: 4O + c1 = O + 10c2 (so the ones digit repeats as O)
  • hundreds: 4T + c2 = O + 10c3, and c3 is G
    Also remember: T and G cannot be 0 (leading letters), and all letters must be different. O cannot be 0 either, or O would equal D.

Here is a small, generic solver that bakes in those carry checks first. It will find the assignment and print the mapping, then verify 4*TOO == GOOD. It runs in a handful of iterations instead of 10P4.

#include <iostream>
using namespace std;

int main() {
    for (int O = 0; O <= 9; ++O) {
        int c1 = (4*O) / 10;
        int D  = (4*O) % 10;
        if (D == O) continue;                 // distinct digits

        int tens = 4*O + c1;
        if (tens % 10 != O) continue;         // ...OO pattern
        int c2 = tens / 10;

        for (int T = 1; T <= 9; ++T) {        // T is leading
            if (T == O || T == D) continue;

            int hund = 4*T + c2;
            if (hund % 10 != O) continue;
            int G = hund / 10;                // carry to thousands
            if (G == 0 || G == T || G == O || G == D) continue;

            int TOO  = 100*T + 10*O + O;
            int GOOD = 1000*G + 100*O + 10*O + D;
            if (4*TOO == GOOD)
                cout << "T="<<T<<" O="<<O<<" G="<<G<<" D="<<D
                     << "  -->  " << 4*TOO << " == " << GOOD << "\n";
        }
    }
}

If you were getting something like 1642 earlier, double-check:

  • Build numbers as TOO = 100T + 10O + O and GOOD = 1000G + 100O + 10*O + D.
  • Enforce all-different digits and the no-leading-zero rule for T and G.
  • Add prints for c1,c2 to see why a candidate fails. ’s idea of trimming the search is spot on; the carry pruning above generalizes it.

Recommended Answers

All 8 Replies

Thanks for the reply but I need make a program using the loop to give me that answer xD

Thanks for the reply but I need make a program using the loop to give me that answer xD

Well if you wanted to, you could just brute-force it. There are only three letters and hence 10 * 9 * 8 possibilities:

for (int g = 0; g < 10; g++)
{
    for (int o = 0; o < 10; o++)
    {
        if (g != o)
        {
             for (int d = 0; d < 10; d++)
             {
                 if (g != d && o != d)
                 {
                      if (SentenceWorks (g, o, d))
                          // display g, o, and d
                 }
             }
        }
    }
}

SentenceWorks is a boolean function that replaces the letters with values, evaluates the terms, and sees if they are the same.

[EDIT]
Whoops. there are four letters, not three, so add a t loop. Same concept though. It's the "dumb", brute force way, bu it'll get the job done. There are probably more elegant solutions.
[/EDIT]

Unfortunetly that code doesnt work for me. I don't get the correct answers with that x_x

Unfortunetly that code doesnt work for me. I don't get the correct answers with that x_x

It will work. Post your code.

this code will solve only this problem and will do it in 36 iterations. just did it for giggles to see if i could. if you want a generic code then you will have to do other things ;)

#include <iostream>
#include <stdlib.h>

using namespace std;

int main()
{
	string too = "", good = "";
	char convert[5];
	int temp;
	for (int i = 1; i < 10; i++)
	{
		for (int j = 0; j < 10; j++)
		{
			if (j == i)
				continue;
			temp = (i * 100) + (j * 10) + j;
			_itoa(temp, convert, 10);
			too = convert;
			_itoa((temp * 4), convert, 10);
			good = convert;
			if ((too[2] == good[1]) && (good[1] == good[2]) && (good[0] != good[3]) && (good[1] != good[3]) && (good.size() == 4))
			{
				cout << "SUCCESS!!!\n";
				cout << "TOO = " << temp << "\n";
				cout << "GOOD = " << (temp * 4) << "\n";
				cin.get();
				return 0;
			}
			cout << "too = " << temp << "\tgood = " << (temp * 4) << "\n";
		}
	}
	cout << "sorry this didnt work.";
	cin.get();
	return 0;
}

Thanks for the suggestion!

#include <iostream>
using namespace std;

int main()
{

    for( int t = 0; t < 10; t++ )
        for( int o = 0; o < 10; o++ )
        // put g starting at 1 so != to 0
            for( int g = 1; g < 10; g++ ) 
                for( int d = 0; d < 10; d++)
                //first if makes sure none of the letter are the same
                    if (t != o && t != d && t != g && g != o && g != d && d != o)
                    //second if checks if they are equal 
                        if ((t*100 + o*10 + o) * 4 == g*1000 + o*100 +o*10 +d){
                            cout << g << o << o << d << " = good\n";
                            cout << t << o << o << " = too";
                        } 
    return 0;
}
commented: This post is over 4 years old? :S! What is the point? -1
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.