#include #include #include #define true (1) #define false (0) #define bool int enum { TYP_NULL, TYP_INP, /* 1 */ TYP_OUT, TYP_CON, /* 3 */ TYP_CROSS, TYP_EQU, /* 5 */ TYP_NEG, TYP_GATE_MAIN, TYP_GATE_PART, TYP_MAX }; #define L_LEFT (0) #define L_RIGHT (1) #define L_TOP (2) #define L_BOT (3) typedef struct node_s { char type; char data; /* 0,1,A-Z */ struct node_s* link[4]; /* GATE */ struct node_s* par; /* link to gate TOP-LEFT node */ char op; /* gate OP */ int ninp; /* gate's no. of inputs */ bool state; int ninp_ok; bool ingate; /* MISC */ struct node_s* next; /* inputs */ int x, y; bool done; } node_t; int dummy1[10000]; char lines[300][300]; int numlines; int lens[300]; int dummy2[10000]; node_t nodes[300][300]; char outs[50]; void fill(node_t* n, int fromdir, bool state) { /* follow, dont forget to fork at '+' ! */ /*printf("FILL> me=%p type=%i from=%i state=%i [L-%p,R-%p,T-%p,B-%p]\n", n, n->type, fromdir, state, n->link[L_LEFT], n->link[L_RIGHT], n->link[L_TOP], n->link[L_BOT]);*/ /*printf("FILL> me=(%i,%i) type=%i from=%i state=%i\n", n->x, n->y, n->type, fromdir, state);*/ /* try move w/o fromdir */ if (n->done && n->type != TYP_CROSS) return; n->done = true; switch (n->type) { case TYP_NULL: /* ignore empty */ /*printf("> EMPTY (%i,%i)\n", n->x, n->y);*/ break; case TYP_INP: fill(n->link[L_RIGHT], L_LEFT, n->data); break; case TYP_OUT: outs[(int)n->data] = state; /*printf("> OUT! '%c'\n", n->data+'A');*/ break; case TYP_CON: if (fromdir!=L_RIGHT && n->link[L_RIGHT]) { fill(n->link[L_RIGHT], L_LEFT, state); } if (fromdir!=L_LEFT && n->link[L_LEFT]) { fill(n->link[L_LEFT], L_RIGHT, state); } if (fromdir!=L_BOT && n->link[L_BOT]) { fill(n->link[L_BOT], L_TOP, state); } if (fromdir!=L_TOP && n->link[L_TOP]) { fill(n->link[L_TOP], L_BOT, state); } break; case TYP_CROSS: /* be carefull */ /*printf("CROSSSSSSSSSSSS\n");*/ if (fromdir==L_LEFT && n->link[L_RIGHT]) { /*printf("AAAAAAAAAAA\n");*/ fill(n->link[L_RIGHT], L_LEFT, state); } if (fromdir==L_RIGHT && n->link[L_LEFT]) { /*printf("BBBBBBBBBB\n");*/ fill(n->link[L_LEFT], L_RIGHT, state); } if (fromdir==L_TOP && n->link[L_BOT]) { /*printf("CCCCCCCCCCCc\n");*/ fill(n->link[L_BOT], L_TOP, state); } if (fromdir==L_BOT && n->link[L_TOP]) { /*printf("DDDDDDDDDDDDdd\n");*/ fill(n->link[L_TOP], L_BOT, state); } break; case TYP_EQU: if (fromdir!=L_RIGHT && n->link[L_RIGHT]) { fill(n->link[L_RIGHT], L_LEFT, state); } if (fromdir!=L_LEFT && n->link[L_LEFT]) { fill(n->link[L_LEFT], L_RIGHT, state); } break; case TYP_NEG: if (fromdir!=L_RIGHT && n->link[L_RIGHT]) { fill(n->link[L_RIGHT], L_LEFT, !state); } if (fromdir!=L_LEFT && n->link[L_LEFT]) { fill(n->link[L_LEFT], L_RIGHT, !state); } break; case TYP_GATE_PART: n = n->par; case TYP_GATE_MAIN: /* fill in input */ if (n->ninp_ok == 0) { n->state = state; n->ninp_ok++; } else { if (n->op == '1') /* OR */ n->state |= state; else if (n->op == '&') /* AND */ n->state &= state; else /* XOR */ n->state ^= state; n->ninp_ok++; } /*printf("GATE-IN> ins=%i dons=%i\n", n->ninp, n->ninp_ok);*/ /* try if can output */ if (n->ninp == n->ninp_ok) fill(n->link[0], L_LEFT, n->state); break; default: /*printf("DBG> fill(%i) switch fall-through!\n", n->type);*/ break; } } void process() { /* clean-up */ int cl; for (cl=0; clx = cc; n->y = cl; /* FIXME edges !!!! */ if (!n->ingate && (c == '0' || c == '1')) { n->type = TYP_INP; n->data = c - '0'; /* save start */ if (!cinp) { cinp = n; } else { n->next = cinp; cinp = n; } } else if (c >= 'A' && c <= 'Z') { n->type = TYP_OUT; n->data = c - 'A'; /*printf("OUTER %c @ (%i,%i)\n", c, n->x, n->y);*/ /* save end */ outs[(int)n->data] = -2; /*printf("DBG> found out %c\n", c);*/ } else if (c == '-') { n->type = TYP_CON; /* find neigh */ node_t* nL = &nodes[cl][cc-1]; node_t* nR = &nodes[cl][cc+1]; /* self */ n->link[L_LEFT] = nL; n->link[L_RIGHT] = nR; /* neigh */ nL->link[L_RIGHT] = n; nR->link[L_LEFT] = n; } else if (c == '|') { n->type = TYP_CON; /* find neigh */ node_t* nT = &nodes[cl-1][cc]; node_t* nB = &nodes[cl+1][cc]; /*printf("DBG> SYM: | me=%p T=%p B=%p\n", n, nT, nB);*/ /* self */ n->link[L_TOP] = nT; n->link[L_BOT] = nB; /* neigh */ nT->link[L_BOT] = n; nB->link[L_TOP] = n; } else if (c == '+') { n->type = TYP_CON; /* find neigh */ node_t* nL = &nodes[cl][cc-1]; node_t* nR = &nodes[cl][cc+1]; node_t* nT = &nodes[cl-1][cc]; node_t* nB = &nodes[cl+1][cc]; /* self */ n->link[L_LEFT] = nL; n->link[L_RIGHT] = nR; n->link[L_TOP] = nT; n->link[L_BOT] = nB; /* neigh */ nL->link[L_RIGHT] = n; nR->link[L_LEFT] = n; nT->link[L_BOT] = n; nB->link[L_TOP] = n; } else if (c == 'o') { n->type = TYP_NEG; /* find neigh */ node_t* nL = &nodes[cl][cc-1]; node_t* nR = &nodes[cl][cc+1]; /* self */ n->link[L_LEFT] = nL; n->link[L_RIGHT] = nR; /* neigh */ nL->link[L_RIGHT] = n; nR->link[L_LEFT] = n; /* gate in left? */ if (lines[cl][cc-1] == '#') nodes[cl][cc-1].par->link[0] = n; } else if (c == 'x') { n->type = TYP_CROSS; /* find neigh */ node_t* nL = &nodes[cl][cc-1]; node_t* nR = &nodes[cl][cc+1]; node_t* nT = &nodes[cl-1][cc]; node_t* nB = &nodes[cl+1][cc]; /* self */ n->link[L_LEFT] = nL; n->link[L_RIGHT] = nR; n->link[L_TOP] = nT; n->link[L_BOT] = nB; /* neigh */ nL->link[L_RIGHT] = n; nR->link[L_LEFT] = n; nT->link[L_BOT] = n; nB->link[L_TOP] = n; } else if (c == '=') { n->type = TYP_EQU; /* find neigh */ node_t* nL = &nodes[cl][cc-1]; node_t* nR = &nodes[cl][cc+1]; /* self */ n->link[L_LEFT] = nL; n->link[L_RIGHT] = nR; /* neigh */ nL->link[L_RIGHT] = n; nR->link[L_LEFT] = n; /* gate in left? */ if (lines[cl][cc-1] == '#') nodes[cl][cc-1].par->link[0] = n; } else if (c == '#') { /* calc ONLY at top left ! */ if (lines[cl+1][cc] == '#' && lines[cl][cc+1] == '#') { n->ninp = 0; n->ninp_ok = 0; n->type = TYP_GATE_MAIN; /* follow all & link together (set par) */ int offx, offy; /* right -> down */ offx = 0; offy = 0; while (lines[cl][cc+offx] == '#') { nodes[cl][cc+offx].par = n; offx++; } offx--; while (lines[cl+offy][cc+offx] == '#') { nodes[cl+offy][cc+offx].par = n; offy++; } offy--; /* down -> right */ offx = 0; offy = 0; while (lines[cl+offy][cc] == '#') { nodes[cl+offy][cc].par = n; /* incr gate inp count */ if (lines[cl+offy][cc-1] == '=') n->ninp++; offy++; } offy--; while (lines[cl+offy][cc+offx] == '#') { nodes[cl+offy][cc+offx].par = n; offx++; } offx--; /* set ingate */ /*printf("GATE> at=(%i,%i) off=(%i,%i)\n",cc,cl,offx,offy);*/ int u, v; for (u=1; u (%i,%i)\n", cc+v,cl+u);*/ nodes[cl+u][cc+v].par = n; nodes[cl+u][cc+v].ingate = true; } } else /*if (lines[cl+1][cc] != '#' && lines[cl][cc+1] != '#')*/ { n->type = TYP_GATE_PART; } } else if (n->ingate && (c == '1' || c == '&' || c == '=')) { n->par->op = c; } } } /* go go go */ while (cinp) { /* try next input and get furthest possible */ /* FIXME can be without inputs? */ node_t* n = cinp; cinp = cinp->next; bool state = n->data; int fromdir = L_LEFT; /*printf("INP> ...\n");*/ fill(n, fromdir, state); } } void output() { int i; for (i=0; i<50; i++) { int o = outs[i]; if (o == 0 || o == 1) printf("%c=%i\n", 'A'+i, o); } printf("\n"); } int main() { int cline = 0+2; while (true) { /* read data */ lines[cline][0] = lines[cline][1] = lines[cline][2] = ' '; fgets(&lines[cline][0+2], 250, stdin); if (lines[cline][0+2] == '*') { if (cline == 0+2) { /* EOF */ return 0; } /* process */ numlines = cline+1; process(); output(); /* next case */ cline = 0+2; continue; } cline++; } return 0; }