2 Simple Numeric Operations
3 (c) 1995 Martin Mares, MJSoft System Software
15 int able[MAXSTEPS+1][MAXNUM];
16 int func[MAXSTEPS+1][MAXNUM];
17 int op1[MAXSTEPS+1][MAXNUM];
18 int op2[MAXSTEPS+1][MAXNUM];
19 int op1l[MAXSTEPS+1][MAXNUM];
20 int op2l[MAXSTEPS+1][MAXNUM];
22 int penalty[MAXSTEPS+1][MAXNUM];
24 int maxdisp,digit,maxsteps,maxnum;
26 /* 0 1 2 3 4 5 6 7 8 9 10 1112 13 */
28 int pen[] = { 1,1,2,2,6,3,60,30,60,6,4,20,3,150,150 };
30 int pen[] = { 1,1,2,2,5,3,8 ,6 ,8 ,5,4,6 ,3,13 ,13 };
32 /* + - * / % ^ @ C $ \ ! S R r t */
33 int pri[] = { 2,2,3,3,4,5,3, 7, 3, 3,9,7, 7,7, 7 };
35 /* PRI == 7 <=> left-associative function with no priority */
37 int op(int code,int a,int b,int src1,int src2)
45 case 3: if (b && !(a%b)) return a/b; else return -1; /* DIV */
46 case 4: if (b) return a%b; else return -1; /* MODULO */
47 case 5: i=1; /* POWER */
51 if (i >= maxnum) return -1;
54 case 6: if (!b || a%b || able[src2][b] != 2) return -1; /* A/.(B) */
63 case 7: if (a < b) return -1; /* COMBINATION */
67 while (k<=b && !(i%k))
78 if (i>100000) return -1;
81 case 8: if (!b || a%b || able[src2][b] != 2) return -1; /* A/.B */
90 case 9: if (b) return a/b; else return -1; /* DIV */
91 case FIRSTUNARY: i=1; /* FACT */
95 if (i >= maxnum) return -1;
99 case FIRSTUNARY+1: if (a) return 1; else return 0; /* SIGNUM */
100 case FIRSTUNARY+2: for(i=0;i<maxnum;i++) /* ROOT */
103 if (j == a) return i;
104 if (j > a) return -1;
107 case FIRSTUNARY+3: for(i=0;i<maxnum;i++) /* UPPER ROOT */
110 if (j >= a) return i;
113 case FIRSTUNARY+4: for(i=0;i<maxnum;i++) /* LOWER ROOT */
116 if (j == a) return i;
117 if (j > a) return i-1;
124 int doop(int dest,int k,int i,int j,int src1,int src2,int p)
126 int l = op(k,i,j,src1,src2);
127 if (l>=0 && l<maxnum)
128 if (!able[dest][l] || penalty[dest][l] > p+pen[k])
133 op1l[dest][l] = src1;
135 op2l[dest][l] = src2;
136 penalty[dest][l] = p+pen[k];
137 if (l > max[dest]) max[dest] = l;
143 void try(int dest,int src1,int src2)
146 fprintf(stderr,"Trying %d %d -> %d\n",src1+1,src2+1,dest+1);
148 for(i=0;i<=max[src1];i++)
151 if (i-l>=10 || i<15) { fprintf(stderr,"%d\r",i); l=i; }
152 for(j=0;j<=max[src2];j++)
154 for(k=0;k<FIRSTUNARY;k++)
155 doop(dest,k,i,j,src1,src2,penalty[src1][i]+penalty[src2][j]);
159 void tryuna(int dest)
162 fprintf(stderr,"Trying unary ops for level %d\n",dest+1);
166 for(i=0;i<=max[dest];i++)
168 for(k=FIRSTUNARY;k<NUMOPS;k++)
169 if (doop(dest,k,i,0,dest,0,penalty[dest][i]))
177 void dump(int level,int i)
179 if (able[level][i] == 2) printf("%d",i);
180 else if (func[level][i] < FIRSTUNARY)
183 dump(op1l[level][i],op1[level][i]);
184 putchar("+-*/%^@C$\\"[func[level][i]]);
185 dump(op2l[level][i],op2[level][i]);
190 putchar("!SRrt"[func[level][i]-FIRSTUNARY]);
192 dump(op1l[level][i],op1[level][i]);
209 #define OP_CONST 0xff
211 char *unam[] = {"sgn","sqr","ceil sqr","int sqr"};
213 struct node *firstfree;
215 struct node *obtain_node(void)
223 else p=malloc(sizeof(struct node));
227 void free_node(struct node *p)
229 p->a[0].p = firstfree;
233 void free_tree(struct node *p)
235 if (p->op != OP_CONST)
237 free_tree(p->a[0].p);
238 if (p->op < FIRSTUNARY) free_tree(p->a[1].p);
243 struct node *build_tree(int level,int i)
245 struct node *p = obtain_node();
246 if (able[level][i] == 2)
253 p->op = func[level][i];
254 p->a[0].p = build_tree(op1l[level][i],op1[level][i]);
255 if (p->op < FIRSTUNARY)
256 p->a[1].p = build_tree(op2l[level][i],op2[level][i]);
261 void print_tree(struct node *n,int p,int orop)
264 if (n->op == OP_CONST) printf("%d",n->a[0].value);
268 || (pri[n->op] == p &&
269 (orop == 1 || orop == 3 || orop == 4 || orop == 6
275 if (n->op <= 5) /* standard binary */
277 print_tree(n->a[0].p,r,n->op);
278 putchar("+-*/%^"[n->op]);
279 print_tree(n->a[1].p,r,n->op);
281 else if (n->op == 6) /* /.() */
283 print_tree(n->a[0].p,r,n->op);
285 print_tree(n->a[1].p,r,n->op);
288 else if (n->op == 7) /* COMB */
291 print_tree(n->a[0].p,r,n->op);
293 print_tree(n->a[1].p,r,n->op);
296 else if (n->op == 8) /* /. */
298 print_tree(n->a[0].p,r,n->op);
300 print_tree(n->a[1].p,r,n->op);
302 else if (n->op == 9) /* DIV */
304 print_tree(n->a[0].p,r,n->op);
306 print_tree(n->a[1].p,r,n->op);
308 else if (n->op == FIRSTUNARY) /* FACT */
310 print_tree(n->a[0].p,r,n->op);
313 else /* classical prefix unary */
315 printf(unam[n->op-FIRSTUNARY-1]);
316 print_tree(n->a[0].p,255,255);
322 void dump(int level,int i)
325 root = build_tree(level,i);
326 print_tree(root,0,-1);
336 for(j=0;j<=maxsteps;j++)
339 if (i>=maxnum) return;
349 for(steps=1;steps<=maxsteps;steps++)
352 try(steps,i,steps-i-1);
362 for(i=0;i<maxdisp;i++)
363 if (able[maxsteps][i])
367 printf(" {%d}\n",penalty[maxsteps][i]);
368 totb += penalty[maxsteps][i];
371 else printf("%d : MISSING\n",i);
372 printf("%d of %d. {%d}\n",steps,maxdisp,totb);
381 int main(int argc,char **argv)
385 printf("Usage: math <digit> <count> <limit> <calclimit>\n");
388 digit = atol(argv[1]);
389 if (digit<0 || digit>9) err("Invalid digit!");
390 maxsteps = atol(argv[2])-1;
391 if (maxsteps<0 || maxsteps>MAXSTEPS) err("Invalid digit count!");
392 maxdisp = atol(argv[3])+1;
393 maxnum = atol(argv[4])+1;
394 if (maxnum<1 || maxnum>MAXNUM) err("Invalid internal maximum!");
395 if (maxdisp<1 || maxdisp>maxnum) err("Invalid limit!");