- /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis 
-  * 
-  *  This program is free software; you can redistribute it and/or modify 
-  *  it under the terms of the GNU General Public License as published by 
-  *  the Free Software Foundation; either version 2 of the License, or 
-  *  (at your option) any later version. 
-  * 
-  *  This program is distributed in the hope that it will be useful, 
-  *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
-  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
-  *  GNU General Public License for more details. 
-  * 
-  *  You should have received a copy of the GNU General Public License 
-  *  along with this program; if not, write to the Free Software 
-  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
-  */ 
-   
-  /* Solves cryptarithms, to be interfaced by wims. */ 
-   
- #define MAX_LINES 64 
- #define MAX_CHARS 32 
-   
- #include "../wims.h" 
-   
- char basetab[MAX_LINES][MAX_CHARS]; 
- int carry[MAX_LINES][MAX_CHARS+8]; 
- char corresp[32],bcorresp[16]; 
- int linecnt,charcnt[MAX_LINES],activelen,maxlen; 
- int active[MAX_LINES]; 
- int style[MAX_LINES]; 
- int total=0; 
-   
- char *input; 
-   
-         /* Print the result */ 
- void printresult(char curr[]) 
- { 
-     int i,j; 
-     char ch; 
-     for(i=0;i<linecnt;i++) { 
-         for(j=0;j<charcnt[i];j++) { 
-             ch=basetab[i][j]; 
-             if(ch==0) ch=' '; 
-             else if(ch>='A' && ch<='Z') ch=curr[ch-'A']; 
-         } 
-     } 
- } 
-   
-         /* returns 1 if OK, 0 if bad. */ 
- int putvalue(char ch, char k, char curr[], char currb[]) 
- { 
-     int i=ch-'A'; 
-     if(ch==0) { 
-         if(k>0) return 0; else return 1; 
-     } 
-     if((curr[i]!=-1 && curr[i]!=k) || (currb[k]!=0 && currb[k]!=ch)) 
-       return 0; 
-     curr[i]=k;currb[k]=ch; return 1; 
- } 
-   
-         /* check that leading number is not 0. Returns 0 if bad. */ 
- int checklead(char curr[]) 
- { 
-     int i; 
-     char ch; 
-     for(i=0;i<linecnt;i++) { 
-         ch=basetab[i][charcnt[i]-1]; 
-         if(curr[ch-'A']<=0) return 0; 
-     } 
-     return 1; 
- } 
-   
-         /* returns 0 if fail, 1 if OK. */ 
- int colcompute(int c,char curr[],char currb[]) 
- { 
-     int i,j,k,sum; 
-     char ch; 
-   
-     switch(style[1]) { 
-         case '-': 
-         case '+': 
-         case '.': { 
-             for(j=sum=0;j<linecnt;j++) { 
-                 if(!active[j]) continue; 
-                 ch=basetab[j][c]; 
-                 if(ch!=0) { 
-                     if(style[j]!='-') sum+=curr[ch-'A']; 
-                     else sum-=curr[ch-'A']; 
-                 } 
-             } 
-             lastline: 
-             sum+=carry[linecnt-1][c]; 
-             carry[linecnt-1][c+1]=(sum+10000)/10-1000; k=(sum+10000)%10; 
-             return putvalue(basetab[linecnt-1][c],k,curr,currb); 
-         } 
-          
-         case '*': { 
-             char c1,c2; 
-             c2=basetab[0][c]; 
-             if(c2!=0) c2=curr[c2-'A']; 
-             for(i=0;i<c && i<linecnt-3;i++) { 
-                 c1=basetab[1][i]; 
-                 if(c2*c1!=0) sum=c2*curr[c1-'A']+carry[2+i][c]; 
-                 else sum=carry[2+i][c]; 
-                 carry[2+i][c+1]=sum/10; 
-                 if(!putvalue(basetab[2+i][c],sum%10,curr,currb)) 
-                   return 0; 
-             } 
-             c2=basetab[1][c]; 
-             if(c2!=0) { 
-                 c2=curr[c2-'A']; 
-                 for(i=0;i<=c;i++) { 
-                     c1=basetab[0][i]; 
-                     if(c1==0) break; 
-                     sum=c2*curr[c1-'A']+carry[2+c][i]; 
-                     carry[2+c][i+1]=sum/10; 
-                     if(!putvalue(basetab[2+c][i],sum%10,curr,currb)) 
-                       return 0; 
-                 } 
-             } 
-             for(i=sum=0;i<=c && i<linecnt-3;i++) { 
-                 ch=basetab[2+i][c-i]; 
-                 if(ch!=0) sum+=curr[ch-'A']; 
-             } 
-             goto lastline; 
-         } 
-          
-                 /* short multiplication */ 
-         case '$': { 
-             char c1,c2; 
-             for(j=sum=0;j<=c;j++) { 
-                 c1=basetab[0][j]; c2=basetab[1][c-j]; 
-                 if(c1==0) break; 
-                 if(c2==0) continue; 
-                 sum+=curr[c1-'A']*curr[c2-'A']; 
-             } 
-             goto lastline; 
-         } 
-          
-          
-         default: return 0; 
-     } 
- } 
-   
- void column(int c, char prev[], char prevb[]) 
- { 
-     char curr[32], currb[16]; 
-     int lreg[MAX_LINES],lfix[MAX_LINES]; 
-     int i,j,icarry; 
-     char ch; 
-   
-   
-     for(i=0;i<linecnt;i++) { 
-         if(!active[i]) continue; 
-         ch=basetab[i][c];  
-         if(ch==0 || prev[ch-'A']!=-1) lfix[i]=1; 
-     } 
-     for(icarry=0;;icarry=1) { 
-         memmove(- currb ,- prevb ,sizeof(- currb ));
 
-         for(i=0;i<linecnt;i++) { 
-             if(!active[i] || lfix[i]) continue; 
-             for(j=lreg[i]+icarry;j<10 && prevb[j]!=0;j++); 
-             if(j>=10) { 
-                 for(j=0;j<10 && prevb[j]!=0;j++); 
-                 if(j>=10) return; 
-                 icarry=1; 
-             } 
-             else icarry=0; 
-             lreg[i]=j; 
-         } 
-         if(icarry) break; 
-         for(i=0;i<linecnt;i++) { 
-             if(!active[i] || lfix[i]) continue; 
-             if(!putvalue(basetab[i][c],lreg[i],curr,currb)) goto loopend; 
-         } 
-         if(!colcompute(c,curr,currb)) continue; 
-         if(c<activelen-1) column(c+1,curr,currb); 
-         else { 
-             for(i=activelen;i<maxlen;i++) { 
-                 if(!colcompute(i,curr,currb)) goto loopend; 
-             } 
-             for(i=0;i<linecnt;i++) { 
-                 if(active[i]) continue; 
-                 if(carry[i][maxlen]) goto loopend; 
-             } 
-             if(!checklead(curr)) goto loopend; 
-             total++; 
-             printresult(curr); 
-         } 
-         loopend: 
-     } 
- } 
-   
- int main(int argc, char *argv[]) 
- { 
-     char *p,*p2,*p3; 
-     int i; 
-     input =getenv("wims_exec_parm");
-         /* nothing to do if no problem */ 
-     if(input==NULL || *input==0) return 0; 
-   
-     memset(- basetab ,0,sizeof(- basetab ));
 
-     memset(- corresp ,-1,sizeof(- corresp ));
 
-     memset(- bcorresp ,0,sizeof(- bcorresp ));
 
-     memset(- carry ,0,sizeof(- carry ));
 
-     memset(- active ,0,sizeof(- active ));
 
-   
-     *p=0; 
-     activelen=maxlen=0; 
-     active[0]=active[1]=1; 
-     for(linecnt=0,p=input;*p!=0 && linecnt<MAX_LINES;p=p3) { 
-         if(p2==NULL) { 
-         } 
-         else p3=p2+1; 
-         if(strchr("+-*/=.",*- p )!=- NULL ) {
 
-             style[linecnt]=*p;p++; 
-         } 
-         else style[linecnt]='+'; 
-         if(*p3==0) style[linecnt]='='; 
-         if(linecnt>1) { 
-             switch(style[1]) { 
-                 case '+': 
-                 case '-': { 
-                     if(*p3!=0) active[linecnt]=1; 
-                     break; 
-                 } 
-                  
-                 case '*': 
-                 case '/': 
-                 case '=': 
-                 break; 
-             } 
-         } 
-         while(- p2 >- p  && isspace(*(- p2 -1)))-  p2 --;
 
-         if(p2>p+MAX_CHARS) p2=p+MAX_CHARS; 
-         *p2=0; 
-         if(p2<=p) continue; 
-         for(i=0;i<p2-p;i++) { 
-             char ch; 
-                 /* bad char */ 
-             if(ch<'A' || ch>'Z') return 1; 
-             basetab[linecnt][i]=ch; 
-         } 
-         charcnt[linecnt]=p2-p; 
-         if(active[linecnt] && p2-p>activelen) activelen=p2-p; 
-         if(p2-p>maxlen) maxlen=p2-p; 
-         linecnt++; 
-     } 
-         /* multiplication */ 
-     if(style[1]=='*') { 
-         if(linecnt==3) style[1]='$'; 
-         else { 
-             if(linecnt!=charcnt[1]+3) return 1; 
-             for(i=3;i<linecnt-1;i++) 
-               if(charcnt[i]+i-2>maxlen) maxlen=charcnt[i]+i-2; 
-         } 
-     } 
-   
-     column(0,corresp,bcorresp); 
- printf("\n!total %d solution(s).\n\n",- total );
 
-     return 0; 
- } 
-   
-