/* - - - - - - - - - - - - - - - - - - - - - *\
*                                             *
|        Lost Alphametics Easy Recovery       |
|                                             |
|  syntax : $laer term(1) ... term(n) sum     |
|  example : to solve SEND + MORE = MONEY :   |
|            $laer send more money            |
|                                             |
*                                             *
\* - - - - - - - - - - - - - - - - - - - - - */

// License : GPL

#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;

// occurence
struct occ        
{
	unsigned char lett;
	short val;
	long coeff;
};

long pow(int x, short n);
void comb (short n, short p, short *p_arr, short lg, short *p_place, occ *lc, int *p_cpt, int argc, char *argv[]);

int main(int argc, char *argv[])
{

	// 1st step : setting each letter "weight"

	if (argc < 4){
		cout << "laer - Lost Alphametics Easy Recovery v0.3\n";
		cout << "http://submoon.freeshell.org/en/laer      \n";
		cout << "syntax : $laer term(1) ... term(n) sum    \n";
		cout << "example : to solve SEND + MORE = MONEY:   \n";
		cout << "          $laer send more money           \n";
		return 0;
	}
  
	cout << "Initializing data...\n";
	
	short place[256];
	for (int i=0; i<256; i++) place[i]=-1;
	short ndc = 0;		// number of different chars
	occ lc[10];			// char list
	for (int i=0; i<10; i++) lc[i].coeff=0;
	short pos = 0;		// 1 if term, -1 if sum

	for (short arg=1; arg<argc; arg++){
		pos = ((arg == argc-1) ? -1 : 1);
		for (short i=0; argv[arg][i]; i++){
			if (place [argv[arg][i]]!=-1)
				lc[place[argv[arg][i]]].coeff += pos*pow(10,strlen(argv[arg])-1-i);
	  		else{
				place[argv[arg][i]]= ndc;
				lc[ndc].lett = argv[arg][i];
				lc[ndc].val = 0;
				lc[ndc].coeff = pos*pow(10,strlen(argv[arg])-1-i);
				ndc++;
				if (ndc>10)
				{
					cout << "Error : too many different characters.\n\n";
					return 0;
				}
			}
		} 
	}


  // 2nd step : brute-force scanning
  
  cout << "Looking for solutions...\n\n";
  int cpt = 0;
  short arr[10];

  comb (10, ndc, arr, ndc, place, lc, &cpt, argc, argv);

 
  cout << "Total : " << cpt << " solution" << (cpt>1?"s":"") << ".\n\n\a";

  return 0;

      
}

// power function
long pow(int x, short n)
{
  long res = 1;
  for (int cx=0; cx<n; cx++)
  res *= x;
  return res;
}

// comb. of p elements of [|0..n-1|], adapted from alg. (thx to Ian Parberry)
void comb (short n, short p, short *p_arr, short lg, short *p_place, occ *lc, int *p_cpt, int argc, char *argv[])
{
  
  if (p == 0)
   
  do 
  {

    long long sum = 0;
    for (short chf=0; chf<lg; chf++)
    {
      lc[chf].val = p_arr[chf];
      sum += lc[chf].val*lc[chf].coeff;
    }
    
    if (sum == 0)
    {
      bool ok = true;
      for (short cy=1; cy<argc;cy++)
      {
        if (lc[p_place[argv[cy][0]]].val == 0)
        ok = false;
      }
      if (ok)
      // 3rd step : displaying results
      {
        for (short i=1; i<argc-1; i++)
        {
          for (short j=strlen(argv[i]); j<strlen(argv[argc-1]); j++)
          cout << ' ';            
          for (short j=0; j<strlen(argv[i]); j++)
          cout << lc[p_place[argv[i][j]]].val;
          cout << '\n';
        }
        for (short j=0; j<strlen(argv[argc-1]); j++)
        cout << '-';
        cout << '\n';
        for (short j=0; j<strlen(argv[argc-1]); j++)
        cout << lc[p_place[argv[argc-1][j]]].val;
        cout << "\n\n";
        (*p_cpt)++;
      }
    }

  } while (std::next_permutation(p_arr,p_arr+lg));

  else
  for (register short i=p; i<=n; i++)
  {
    p_arr[p-1]=i-1;
    comb(i-1, p-1, p_arr, lg, p_place, lc, p_cpt, argc, argv);
  }

}


Little Neo + code2html, 2005

Laer

Home