#include 

main() {
	int i, j, k, l, signflags, triads[30][7], trines[35][3], M[8][8], S[8][8], sgn, bit, t0, t1, t2, a1, a2;
	for(i=0; i< 8; i++) for (j=0; j< 8; j++) M[i][j] = S[i][j] = 0;
	for(i=0; i< 8; i++) M[i][i] = -1;
	FILE *fp;
	fp = fopen("x8.triads","r");	// generated by x8.c (finds all 30 groupings of imaginary units into triadic multiplication table)
	
	for(i=0;i< 30;i++) 	// triads[i][j] gives indices j into list of trines for multiplication table # i
	    fscanf(fp,"%d %d %d %d %d %d %d", &triads[i][0], &triads[i][1], &triads[i][2], &triads[i][3], &triads[i][4], &triads[i][5], &triads[i][6]);
	fclose(fp);
	fp = fopen("magic.hex","w");
	fclose(fp);
	l = 0;
	for(i=1; i< 8; i++)
	  for(j=i+1; j< 8; j++)
	    for(k=j+1; k< 8; k++) {	// construct list of all ordered trines (3 distinct imaginary units, not necessarily closed under mult)
		trines[l][0] = i;
		trines[l][1] = j;
		trines[l++][2] = k;	// "natural sort order"
	    }
// list of associators <=> list of trines
	for(i=0; i< 30; i++) { // for each of the 30 choices of triad sets
		for(signflags=0; signflags< 128; signflags++) { // for each of the sign assignments - set bit N means triad N anticyclic 
			printf("%d %02x\n", i, signflags);
			// first construct the multiplication table M[][], with sign pattern S[][]
			for(j=1; j< 8; j++) {
				M[0][j] = M[j][0] = j;	// 1*j = j*1 = j
				M[j][j] = 0;		// index 0 points to mult unit "1"
				S[j][j] = -1; 	      	// j*j = -1
				S[0][j] = S[j][0] = 1;	// 1*j = j*1 = +j
			}
			for(j=0; j< 7; j++) {
				M[trines[triads[i][j]][0]][trines[triads[i][j]][1]] = trines[triads[i][j]][2];
				M[trines[triads[i][j]][1]][trines[triads[i][j]][2]] = trines[triads[i][j]][0];
				M[trines[triads[i][j]][2]][trines[triads[i][j]][0]] = trines[triads[i][j]][1];
				M[trines[triads[i][j]][1]][trines[triads[i][j]][0]] = trines[triads[i][j]][2];
				M[trines[triads[i][j]][2]][trines[triads[i][j]][1]] = trines[triads[i][j]][0];
				M[trines[triads[i][j]][0]][trines[triads[i][j]][2]] = trines[triads[i][j]][1];
				sgn = 1;
				bit = 1;
				for(k=0; k< j; k++) bit *= 2;
				if(signflags & bit) sgn = -1;
				S[trines[triads[i][j]][0]][trines[triads[i][j]][1]] = sgn;
				S[trines[triads[i][j]][1]][trines[triads[i][j]][2]] = sgn;
				S[trines[triads[i][j]][2]][trines[triads[i][j]][0]] = sgn;
				S[trines[triads[i][j]][1]][trines[triads[i][j]][0]] = -sgn;
				S[trines[triads[i][j]][2]][trines[triads[i][j]][1]] = -sgn;
				S[trines[triads[i][j]][0]][trines[triads[i][j]][2]] = -sgn;
			}
			// now use the mult tables to test associators (ab)c vs. a(bc)
			bit = 0;
			for(t0=1; t0< 8; t0++)
			for(t1=1; t1< 8; t1++)
			for(t2=1; t2< 8; t2++) {
				a1 = S[t0][M[t1][t2]]*S[t1][t2]*M[t0][M[t1][t2]];
				a2 = S[M[t0][t1]][t2]*S[t0][t1]*M[M[t0][t1]][t2];
				if(a1==a2) {
					bit++;
					printf("%d. %d(%d%d): ", bit, t0, t1, t2);
					printf("%d  ", a1); 
					printf("(%d%d)%d: ", t0, t1, t2);
					printf("%d\n", a2);
				}
			}
			if(bit == 175) {
				fp = fopen("magic.hex","a");
				fprintf(fp,"%02x ", signflags);
				fclose(fp);
			}
		}
		fp = fopen("magic.hex", "a");
		fprintf(fp,"\n");
		fclose(fp);
	}
}