#define _ISOC99_SOURCE #include #include #include #include typedef long long llong; typedef struct { void *next; llong value; } list; list *stack = NULL; const llong ERROR = -2000000001; #define error() do return ERROR; while (0) static inline llong count(); static inline llong pop(); #define MAX 1000000000 #define too_big(x) (llabs(x) > MAX) static inline int overflow() { if (stack && too_big(stack->value)) return 1; if (stack && stack->next && too_big(((list*)stack->next)->value)) return 1; return 0; } static inline int is_error(llong x) { return ERROR == x || overflow(); } #define at_least(x) do if (count() < (x)) error(); while (0) #define streq(x, y) (!strcmp((x), (y))) static inline llong push(llong val) { list *new = malloc(sizeof(*new)); new->value = val; new->next = stack; stack = new; return val; } static inline llong dup() { at_least(1); return push(stack->value); } static inline llong inv() { at_least(1); return stack->value *= -1; } static inline llong swp() { at_least(2); llong tmp = stack->value; stack->value = ((list*) stack->next)->value; ((list*) stack->next)->value = tmp; return 0; } static inline llong add() { at_least(2); llong left = stack->value; if (is_error(pop())) error(); if (fabs((1.0*left)+(1.0*stack->value)) > MAX) error(); stack->value += left; return stack->value; } static inline llong mul() { at_least(2); llong left = stack->value; if (is_error(pop())) error(); if (fabs((1.0*left)*(1.0*stack->value)) > MAX) error(); stack->value *= left; return stack->value; } static inline llong pop() { at_least(1); list *old = stack; stack = stack->next; free(old); return 0; } static inline llong sub() { at_least(2); if (is_error(inv())) error(); return add(); } static inline llong div_() { at_least(2); llong left = stack->value; if (!left || is_error(pop())) error(); stack->value /= left; return stack->value; } #define sgn(x) (((x) > 0) ? 1 : -1) static inline llong mod_() { at_least(2); llong left = stack->value; left = llabs(left); if (!left || is_error(pop())) error(); int sign = sgn(stack->value); stack->value = llabs(stack->value); stack->value = (stack->value % left) * sign; return stack->value; } static inline llong count() { list *cur = stack; llong cnt = 0; while (cur) { cur = cur->next; ++cnt; } return cnt; } #define break_on_error(x) if (is_error(x)) break; enum ops { NUM, POP, INV, DUP, SWP, ADD, SUB, MUL, DIV, MOD, END, QUIT, TOTAL }; void panic() { for (;;) stack = malloc(1000); } const llong OPS_MAX = 2000000; int parse_ops(int *ops) { int ptr = 0; for (;;) { if (OPS_MAX == ptr) panic(); char op[4] = {0}; scanf("%3s", op); if (streq(op, "NUM")) { llong number; scanf("%c", (char*) &number); ops[ptr++] = NUM; scanf("%lli\n", &number); ops[ptr++] = number; } else if (streq(op, "ADD")) { ops[ptr++] = ADD; } else if (streq(op, "SUB")) { ops[ptr++] = SUB; } else if (streq(op, "DUP")) { ops[ptr++] = DUP; } else if (streq(op, "SWP")) { ops[ptr++] = SWP; } else if (streq(op, "INV")) { ops[ptr++] = INV; } else if (streq(op, "DIV")) { ops[ptr++] = DIV; } else if (streq(op, "POP")) { ops[ptr++] = POP; } else if (streq(op, "MOD")) { ops[ptr++] = MOD; } else if (streq(op, "MUL")) { ops[ptr++] = MUL; } else if (streq(op, "END")) { ops[ptr++] = END; break; } else if (streq(op, "QUI")) { ops[ptr++] = QUIT; break; } else { printf("WTF?! %s\n", op); panic(); } if (!streq(op, "NUM")) scanf("\n"); } return 0; } int execute(int *ops) { int ptr = -1; llong ret = 0; for (;;) { ptr++; switch (ops[ptr]) { case NUM: { llong val = ops[ptr + 1]; if (val < 0 || val > 1000000000LL) { ret = ERROR; break_on_error(ret); } else { push(val); ptr++; } } break; case ADD: ret = add(); break_on_error(ret); break; case SUB: ret = sub(); break_on_error(ret); break; case DUP: ret = dup(); break_on_error(ret); break; case SWP: ret = swp(); break_on_error(ret); break; case INV: ret = inv(); break_on_error(ret); break; case DIV: ret = div_(); break_on_error(ret); break; case MOD: ret = mod_(); break_on_error(ret); break; case POP: ret = pop(); break_on_error(ret); break; case MUL: ret = mul(); break_on_error(ret); break; case END: break; default: //printf("WTF OP?! %i/%i\n", ops[ptr], TOTAL); ret = ERROR; break_on_error(ret); } if (ops[ptr] == END || ERROR == ret) break; } if (count() == 1 && !is_error(ret)) { printf("%lli\n", stack->value); } else { printf("ERROR\n"); } return 0; } static inline void free_stack() { #if 0 list *cur = stack; while (cur) { list *old = cur; cur = cur->next; free(old); } #endif stack = NULL; } int main() { int *ops = malloc(OPS_MAX*sizeof(*ops)), i, total_values, value; for (;;) { parse_ops(ops); if (ops[0] == QUIT) return 0; scanf("%i\n", &total_values); for (i = 0; i < total_values; ++i) { scanf("%i\n", &value); free_stack(); push(value); execute(ops); } scanf("\n"); printf("\n"); } return 0; } /* */