#include #include #include #include /* Define a structure to store all expressions of n */ typedef struct { int n; /* The number n */ int nexpr; /* The number of expressions for n */ char **expr; /* The expressions stored in an array of NULL-terminated strings */ char *etype; /* Type of the expressions: additive (+) or multiplicative (*) */ int *ncomp; /* Number of components (summands for additive, and factors for multiplicative) */ int **cval; /* The component values */ int **cidx; /* The index of the component expression in the list for the component */ } EXPR; /* Combine two expressions for j and k to an expression for j op k */ int combineexpr ( char *str, int *cval, int *cidx, int n, EXPR *F, int j, int u, int k, int v, char op ) { char e1type, e2type, *tmp; int ncomp, ncomp1, ncomp2, *cval1, *cval2, *cidx1, *cidx2, i, w1, w2, src; int alloc1, alloc2; /* A temporary string for storing intermediate expressions */ tmp = (char *)malloc(4 * n * sizeof(char)); /* Types of the the u-th expression for j and v-th expression for k */ e1type = F[j].etype[u]; e2type = F[k].etype[v]; if (op == '+') { /* Set n = j + k, and store in the list for n if this is a new expression */ if (e1type == '+') { /* The expression for j is additive, so use the summand list for j */ ncomp1 = F[j].ncomp[u]; cval1 = F[j].cval[u]; cidx1 = F[j].cidx[u]; alloc1 = 0; } else { /* The expression for j is multiplicative, so a single summand is created for k */ ncomp1 = 1; cval1 = (int *)malloc(sizeof(int)); cval1[0] = j; cidx1 = (int *)malloc(sizeof(int)); cidx1[0] = u; alloc1 = 1; } if (e2type == '+') { /* Likewise for k */ ncomp2 = F[k].ncomp[v]; cval2 = F[k].cval[v]; cidx2 = F[k].cidx[v]; alloc2 = 0; } else { ncomp2 = 1; cval2 = (int *)malloc(sizeof(int)); cval2[0] = k; cidx2 = (int *)malloc(sizeof(int)); cidx2[0] = v; alloc2 = 1; } /* Merge the summand lists for j and k. The summand list should be kept sorted, first with respect to summand values, and then with respect to the expression indices. */ w1 = w2 = 0; ncomp = ncomp1 + ncomp2; i = 0; strcpy(str, ""); while ((w1 < ncomp1) || (w2 < ncomp2)) { /* First find from where to take the next summand */ if (w2 == ncomp2) src = 1; else if (w1 == ncomp1) src = 2; else if (cval1[w1] < cval2[w2]) src = 1; else if ((cval1[w1] == cval2[w2]) && (cidx1[w1] <= cidx2[w2])) src = 1; else src = 2; if (src == 1) { /* Read summand from the expression of j */ sprintf(tmp, "%s%s%s", str, (strlen(str) == 0) ? "" : "+", F[cval1[w1]].expr[cidx1[w1]]); strcpy(str, tmp); cval[i] = cval1[w1]; cidx[i] = cidx1[w1]; ++w1; ++i; } else { /* Read summand from the expression of k */ sprintf(tmp, "%s%s%s", str, (strlen(str) == 0) ? "" : "+", F[cval2[w2]].expr[cidx2[w2]]); strcpy(str, tmp); cval[i] = cval2[w2]; cidx[i] = cidx2[w2]; ++w2; ++i; } } } else { /* Set n = j * k, and store in the list for n if this is a new expression */ if (e1type == '*') { /* j is multiplicative, so the components are the factors of j */ ncomp1 = F[j].ncomp[u]; cval1 = F[j].cval[u]; cidx1 = F[j].cidx[u]; alloc1 = 0; } else { /* j is additive, so a single new parenthesized factor is created */ ncomp1 = 1; cval1 = (int *)malloc(sizeof(int)); cval1[0] = j; cidx1 = (int *)malloc(sizeof(int)); cidx1[0] = u; alloc1 = 1; } if (e2type == '*') { /* Likewise for k */ ncomp2 = F[k].ncomp[v]; cval2 = F[k].cval[v]; cidx2 = F[k].cidx[v]; alloc2 = 0; } else { ncomp2 = 1; cval2 = (int *)malloc(sizeof(int)); cval2[0] = k; cidx2 = (int *)malloc(sizeof(int)); cidx2[0] = v; alloc2 = 1; } /* Merge the components in sorted order again */ w1 = w2 = 0; ncomp = ncomp1 + ncomp2; i = 0; strcpy(str, ""); while ((w1 < ncomp1) || (w2 < ncomp2)) { if (w2 == ncomp2) src = 1; else if (w1 == ncomp1) src = 2; else if (cval1[w1] < cval2[w2]) src = 1; else if ((cval1[w1] == cval2[w2]) && (cidx1[w1] <= cidx2[w2])) src = 1; else src = 2; /* Copy factor from the appropriate source. Protect the factor by parentheses if and only if it is an additive expression. */ if (src == 1) { if (strlen(str) == 0) { if ( (e1type == '+') || (F[cval1[w1]].etype[cidx1[w1]] == '+') ) sprintf(tmp, "(%s)", F[cval1[w1]].expr[cidx1[w1]]); else sprintf(tmp, "%s", F[cval1[w1]].expr[cidx1[w1]]); } else { if ( (e1type == '+') || (F[cval1[w1]].etype[cidx1[w1]] == '+') ) sprintf(tmp, "%s*(%s)", str, F[cval1[w1]].expr[cidx1[w1]]); else sprintf(tmp, "%s*%s", str, F[cval1[w1]].expr[cidx1[w1]]); } strcpy(str, tmp); cval[i] = cval1[w1]; cidx[i] = cidx1[w1]; ++w1; ++i; } else { if (strlen(str) == 0) { if ( (e2type == '+') || (F[cval2[w2]].etype[cidx2[w2]] == '+') ) sprintf(tmp, "(%s)", F[cval2[w2]].expr[cidx2[w2]]); else sprintf(tmp, "%s", F[cval2[w2]].expr[cidx2[w2]]); } else { if ( (e2type == '+') || (F[cval2[w2]].etype[cidx2[w2]] == '+') ) sprintf(tmp, "%s*(%s)", str, F[cval2[w2]].expr[cidx2[w2]]); else sprintf(tmp, "%s*%s", str, F[cval2[w2]].expr[cidx2[w2]]); } strcpy(str, tmp); cval[i] = cval2[w2]; cidx[i] = cidx2[w2]; ++w2; ++i; } } } free(tmp); if (alloc1) { free(cval1); free(cidx1); } if (alloc2) { free(cval2); free(cidx2); } return ncomp; } EXPR findallexpr ( int n ) { EXPR E, *F; int i, j, k, l, s, u, v, w; char *str; int *cval, *cidx, ncomp; str = (char *)malloc(4 * n * sizeof(char)); /* For generated expressions */ cval = (int *)malloc(n * sizeof(int)); /* Array of component values */ cidx = (int *)malloc(n * sizeof(int)); /* Array of component indices */ F = (EXPR *)malloc((n+1) * sizeof(EXPR)); /* F is an array of structures of type EXPR */ /* 0 has no representation */ F[0].n = 0; F[0].nexpr = 0; F[0].expr = NULL; F[0].etype = NULL; F[0].ncomp = NULL; F[0].cval = NULL; F[0].cidx = NULL; /* 1 has only one expression: 1 (additive) */ F[1].n = 1; F[1].nexpr = 1; F[1].expr = (char **)malloc(sizeof(char *)); F[1].expr[0] = (char *)malloc(2 * sizeof(char)); strcpy(F[1].expr[0], "1"); F[1].etype = (char *)malloc(sizeof(char)); F[1].etype[0] = '+'; F[1].ncomp = (int *)malloc(sizeof(int)); F[1].ncomp[0] = 1; F[1].cval = (int **)malloc(sizeof(int *)); F[1].cval[0] = (int *)malloc(sizeof(int)); F[1].cval[0][0] = 1; F[1].cidx = (int **)malloc(sizeof(int *)); F[1].cidx[0] = (int *)malloc(sizeof(int)); F[1].cidx[0][0] = 0; /* Generate and store all expressions for i = 2, 3, ..., n */ for (i=2; i<=n; ++i) { /* First compute an upper bound on the number of possible expressions for i */ l = 0; for (j=1; j<=i/2; ++j) { /* Additive expressions */ k = i - j; l += F[j].nexpr * F[k].nexpr; } s = (int)sqrt(i); for (j=2; j<=s; ++j) { /* Multiplicative expressions */ if (i % j == 0) { k = i / j; l += F[j].nexpr * F[k].nexpr; } } /* Initially allocate memory based on the upper bound l */ F[i].n = i; F[i].nexpr = l; F[i].expr = (char **)malloc(l * sizeof(char *)); F[i].etype = (char *)malloc(l * sizeof(char)); F[i].ncomp = (int *)malloc(l * sizeof(int)); F[i].cval = (int **)malloc(l * sizeof(int *)); F[i].cidx = (int **)malloc(l * sizeof(int *)); /* Now identify all different expressions */ l = 0; for (j=1; j<=i/2; ++j) { /* Additive expressions */ k = i - j; /* i = k + j */ for (u=0; u=0; --j) { for (i=0; i<=j; ++i) { /* First compare number of ones */ if (N1[i] > N1[i+1]) continue; /* In case of a tie, compare the expression lengths */ if ((N1[i] == N1[i+1]) && (strlen(E.expr[i]) >= strlen(E.expr[i+1]))) continue; /* Swap if the i-th and the (i+1)-th expressions are out of order */ k = N1[i]; N1[i] = N1[i+1]; N1[i+1] = k; t = E.expr[i]; E.expr[i] = E.expr[i+1]; E.expr[i+1] = t; c = E.etype[i]; E.etype[i] = E.etype[i+1]; E.etype[i+1] = c; k = E.ncomp[i]; E.ncomp[i] = E.ncomp[i+1]; E.ncomp[i+1] = k; p = E.cval[i]; E.cval[i] = E.cval[i+1]; E.cval[i+1] = p; p = E.cidx[i]; E.cidx[i] = E.cval[i+1]; E.cidx[i+1] = p; } } free(N1); } void printallexpr ( EXPR E ) { int l, k; printf("%-3d", E.n); for (l=0; l 1) n = atoi(argv[1]); else scanf("%d", &n); printf("\nn = %d\n", n); E = findallexpr(n); printf("\n+++ Before sorting\n"); printallexpr(E); sortexpr(E); printf("\n+++ After sorting\n"); printallexpr(E); exit(0); }