Files
CodeObject/storage/zeta/c/completed/3425.c
2025-11-08 05:31:00 +09:00

315 lines
8.1 KiB
C

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef enum {
POP,
NUM,
INV,
DUP,
SWP,
ADD,
SUB,
MUL,
DIV,
MOD,
END,
ERR,
QUIT,
} InstructionType;
typedef struct {
InstructionType type;
int32_t num;
} Instruction;
/**
* Stack Implementation
*/
typedef struct {
int32_t size;
int32_t data[1003];
} Stack;
int32_t stack_is_empty(Stack *stack) {
return stack->size == 0;
}
int32_t stack_push(Stack *stack, int32_t num) {
stack->data[stack->size] = num;
stack->size++;
return 1;
}
int32_t stack_pop(Stack *stack, int32_t *out) {
if (stack_is_empty(stack)) {
return 0;
} else {
*out = stack->data[stack->size - 1];
stack->size--;
return 1;
}
}
int32_t stack_clear(Stack *stack) {
stack->size = 0;
return 1;
}
int32_t stack_free(Stack *stack) {
free(stack);
return 1;
}
/**
* Program Executor
*/
typedef struct {
size_t pc;
size_t inst_size;
Stack *stack;
char *string_buff;
Instruction *instructions;
} ProgramExecutor;
void init_executor(ProgramExecutor *executor) {
if (executor->stack == NULL) {
executor->stack = malloc(sizeof(Stack));
}
if (executor->string_buff == NULL) {
executor->string_buff = calloc(100, sizeof(char));
}
if (executor->instructions == NULL) {
executor->instructions = calloc(100002, sizeof(Instruction));
}
executor->pc = 0;
executor->inst_size = 0;
stack_clear(executor->stack);
}
void reset_executor(ProgramExecutor *executor) {
stack_clear(executor->stack);
executor->pc = 0;
}
void delete_executor(ProgramExecutor *executor) {
free(executor->string_buff);
stack_free(executor->stack);
free(executor->instructions);
free(executor);
}
int32_t fetch_instruction(ProgramExecutor *executor) {
Instruction inst;
int num;
scanf("%s", executor->string_buff);
if (!strcmp(executor->string_buff, "POP")) {
inst.type = POP;
} else if (!strcmp(executor->string_buff, "NUM")) {
inst.type = NUM;
scanf("%d", &num);
inst.num = num;
} else if (!strcmp(executor->string_buff, "INV")) {
inst.type = INV;
} else if (!strcmp(executor->string_buff, "DUP")) {
inst.type = DUP;
} else if (!strcmp(executor->string_buff, "SWP")) {
inst.type = SWP;
} else if (!strcmp(executor->string_buff, "ADD")) {
inst.type = ADD;
} else if (!strcmp(executor->string_buff, "SUB")) {
inst.type = SUB;
} else if (!strcmp(executor->string_buff, "MUL")) {
inst.type = MUL;
} else if (!strcmp(executor->string_buff, "DIV")) {
inst.type = DIV;
} else if (!strcmp(executor->string_buff, "MOD")) {
inst.type = MOD;
} else if (!strcmp(executor->string_buff, "END")) {
inst.type = END;
} else if (!strcmp(executor->string_buff, "QUIT")) {
inst.type = QUIT;
} else {
inst.type = ERR;
}
executor->instructions[executor->inst_size] = inst;
executor->inst_size++;
if (inst.type == QUIT || inst.type == ERR) {
return -1;
} else if (inst.type == END) {
return 0;
} else {
return 1;
}
}
int32_t execute_once(ProgramExecutor *executor) {
Instruction instruction = executor->instructions[executor->pc];
executor->pc++;
int error_flag = 0;
int temp = 0, temp2;
switch (instruction.type) {
case POP:
if (!stack_pop(executor->stack, &temp)) {
error_flag = 1;
}
break;
case NUM:
if (!stack_push(executor->stack, instruction.num)) {
error_flag = 1;
}
break;
case INV:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_push(executor->stack, -temp)) error_flag = 1;
break;
case DUP:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_push(executor->stack, temp)) error_flag = 1;
if (!stack_push(executor->stack, temp)) error_flag = 1;
break;
case SWP:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_pop(executor->stack, &temp2)) error_flag = 1;
if (!stack_push(executor->stack, temp)) error_flag = 1;
if (!stack_push(executor->stack, temp2)) error_flag = 1;
break;
case ADD:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_pop(executor->stack, &temp2)) error_flag = 1;
temp = temp2 + temp;
if (abs(temp) > 1000000000) {
error_flag = 1;
break;
}
if (!stack_push(executor->stack, temp)) error_flag = 1;
break;
case SUB:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_pop(executor->stack, &temp2)) error_flag = 1;
temp = temp2 - temp;
if (abs(temp) > 1000000000) {
error_flag = 1;
break;
}
if (!stack_push(executor->stack, temp)) error_flag = 1;
break;
case MUL:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_pop(executor->stack, &temp2)) error_flag = 1;
/* considering mult overflow */
if (temp == 0 || temp2 == 0) {
temp = temp * temp2;
} else if (abs(temp) > abs(1000000000 / temp2)) {
error_flag = 1;
break;
} else {
temp = temp * temp2;
}
if (!stack_push(executor->stack, temp)) error_flag = 1;
break;
case DIV:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_pop(executor->stack, &temp2)) error_flag = 1;
if (temp == 0) {
error_flag = 1;
break;
}
temp = temp2 / temp;
if (abs(temp) > 1000000000) {
error_flag = 1;
break;
}
if (!stack_push(executor->stack, temp)) error_flag = 1;
break;
case MOD:
if (!stack_pop(executor->stack, &temp)) error_flag = 1;
if (!stack_pop(executor->stack, &temp2)) error_flag = 1;
if (temp == 0) {
error_flag = 1;
break;
}
temp = temp2 % temp;
if (abs(temp) > 1000000000) {
error_flag = 1;
break;
}
if (!stack_push(executor->stack, temp)) error_flag = 1;
break;
case END:
return 0;
case QUIT:
case ERR:
return -1;
}
if (error_flag) {
return -1;
}
return 1;
}
int main(void) {
ProgramExecutor *executor = malloc(sizeof(ProgramExecutor));
executor->stack = NULL;
executor->string_buff = NULL;
executor->instructions = NULL;
while (1) {
init_executor(executor);
int32_t signal;
signal = fetch_instruction(executor);
if (signal == -1) {
break;
} else if (signal == 0) {
} else {
while (fetch_instruction(executor) == 1) {
}
}
size_t tc;
int32_t input;
int32_t temp;
scanf("%zu", &tc);
for (size_t i = 0; i < tc; i++) {
reset_executor(executor);
scanf("%d", &input);
stack_push(executor->stack, input);
do {
signal = execute_once(executor);
} while (signal == 1);
if (signal == -1) {
printf("ERROR\n");
} else {
if (executor->stack->size == 1) {
stack_pop(executor->stack, &temp);
printf("%d\n", temp);
} else {
printf("ERROR\n");
}
}
}
printf("\n");
}
delete_executor(executor);
executor = NULL;
return 0;
}