You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
176 lines
4.0 KiB
176 lines
4.0 KiB
6 years ago
|
#include <stdlib.h>
|
||
|
#include <stdio.h>
|
||
|
|
||
|
#include <glib.h>
|
||
|
|
||
|
#define REGS 4
|
||
|
|
||
|
enum instr_id {
|
||
|
INSTR_ADDR,
|
||
|
INSTR_ADDI,
|
||
|
INSTR_MULR,
|
||
|
INSTR_MULI,
|
||
|
INSTR_BANR,
|
||
|
INSTR_BANI,
|
||
|
INSTR_BORR,
|
||
|
INSTR_BORI,
|
||
|
INSTR_SETR,
|
||
|
INSTR_SETI,
|
||
|
INSTR_GTIR,
|
||
|
INSTR_GTRI,
|
||
|
INSTR_GTRR,
|
||
|
INSTR_EQIR,
|
||
|
INSTR_EQRI,
|
||
|
INSTR_EQRR,
|
||
|
INSTR_ID_COUNT
|
||
|
};
|
||
|
|
||
|
struct instr {
|
||
|
enum instr_id i;
|
||
|
int a;
|
||
|
int b;
|
||
|
int c;
|
||
|
};
|
||
|
|
||
|
struct sample {
|
||
|
int before[REGS];
|
||
|
int after[REGS];
|
||
|
struct instr instr;
|
||
|
};
|
||
|
|
||
|
const char *instr_str[] = {
|
||
|
"addr",
|
||
|
"addi",
|
||
|
"mulr",
|
||
|
"muli",
|
||
|
"banr",
|
||
|
"bani",
|
||
|
"borr",
|
||
|
"bori",
|
||
|
"setr",
|
||
|
"seti",
|
||
|
"gtir",
|
||
|
"gtri",
|
||
|
"gtrr",
|
||
|
"eqir",
|
||
|
"eqri",
|
||
|
"eqrr"
|
||
|
};
|
||
|
|
||
|
void instr_interpret(int *r, struct instr *i)
|
||
|
{
|
||
|
switch (i->i) {
|
||
|
case INSTR_ADDR:
|
||
|
case INSTR_MULR:
|
||
|
case INSTR_BANR:
|
||
|
case INSTR_BORR:
|
||
|
case INSTR_GTRR:
|
||
|
case INSTR_EQRR:
|
||
|
if (i->b >= REGS) return;
|
||
|
// fallthrough
|
||
|
case INSTR_ADDI:
|
||
|
case INSTR_MULI:
|
||
|
case INSTR_BANI:
|
||
|
case INSTR_BORI:
|
||
|
case INSTR_SETR:
|
||
|
case INSTR_GTRI:
|
||
|
case INSTR_EQRI:
|
||
|
if (i->a >= REGS) return;
|
||
|
// fallthrough
|
||
|
case INSTR_SETI:
|
||
|
if (i->c >= REGS) return;
|
||
|
break;
|
||
|
|
||
|
case INSTR_GTIR:
|
||
|
case INSTR_EQIR:
|
||
|
if (i->b >= REGS) return;
|
||
|
if (i->c >= REGS) return;
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
switch (i->i) {
|
||
|
case INSTR_ADDR: r[i->c] = r[i->a] + r[i->b]; break;
|
||
|
case INSTR_ADDI: r[i->c] = r[i->a] + i->b; break;
|
||
|
case INSTR_MULR: r[i->c] = r[i->a] * r[i->b]; break;
|
||
|
case INSTR_MULI: r[i->c] = r[i->a] * i->b; break;
|
||
|
case INSTR_BANR: r[i->c] = r[i->a] & r[i->b]; break;
|
||
|
case INSTR_BANI: r[i->c] = r[i->a] & i->b; break;
|
||
|
case INSTR_BORR: r[i->c] = r[i->a] | r[i->b]; break;
|
||
|
case INSTR_BORI: r[i->c] = r[i->a] | i->b; break;
|
||
|
case INSTR_SETR: r[i->c] = r[i->a]; break;
|
||
|
case INSTR_SETI: r[i->c] = i->a; break;
|
||
|
case INSTR_GTIR: r[i->c] = (i->a > r[i->b]) ? 1 : 0; break;
|
||
|
case INSTR_GTRI: r[i->c] = (r[i->a] > i->b) ? 1 : 0; break;
|
||
|
case INSTR_GTRR: r[i->c] = (r[i->a] > r[i->b]) ? 1 : 0; break;
|
||
|
case INSTR_EQIR: r[i->c] = (i->a == r[i->b]) ? 1 : 0; break;
|
||
|
case INSTR_EQRI: r[i->c] = (r[i->a] == i->b) ? 1 : 0; break;
|
||
|
case INSTR_EQRR: r[i->c] = (r[i->a] == r[i->b]) ? 1 : 0; break;
|
||
|
default: break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
struct sample *parse_samples(const char *fname, int *len)
|
||
|
{
|
||
|
FILE *f = fopen(fname, "r");
|
||
|
if (!f) {
|
||
|
perror(fname);
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
GArray *array = g_array_new(FALSE, FALSE, sizeof(struct sample));
|
||
|
|
||
|
// Haha what is proper parsing
|
||
|
struct sample sample;
|
||
|
while (fscanf(f,
|
||
|
"Before: [%d, %d, %d, %d]\n"
|
||
|
"%d %d %d %d\n"
|
||
|
"After: [%d, %d, %d, %d]\n\n",
|
||
|
&sample.before[0], &sample.before[1],
|
||
|
&sample.before[2], &sample.before[3],
|
||
|
(int *)&sample.instr.i, &sample.instr.a,
|
||
|
&sample.instr.b, &sample.instr.c,
|
||
|
&sample.after[0], &sample.after[1],
|
||
|
&sample.after[2], &sample.after[3]
|
||
|
) == 12) {
|
||
|
g_array_append_val(array, sample);
|
||
|
}
|
||
|
|
||
|
fclose(f);
|
||
|
|
||
|
*len = array->len;
|
||
|
return (struct sample *)g_array_free(array, FALSE);
|
||
|
}
|
||
|
|
||
|
int main()
|
||
|
{
|
||
|
int samples_len = 0;
|
||
|
struct sample *samples = parse_samples("input", &samples_len);
|
||
|
if (!samples) return 1;
|
||
|
|
||
|
int *regs = g_new0(int, REGS);
|
||
|
int result = 0;
|
||
|
for (struct sample *sample = samples;
|
||
|
sample < samples + samples_len; sample++) {
|
||
|
int pass = 0;
|
||
|
struct instr instr;
|
||
|
memcpy(&instr, &sample->instr, sizeof(struct instr));
|
||
|
for (enum instr_id i = 0; i < INSTR_ID_COUNT; i++) {
|
||
|
instr.i = i;
|
||
|
memcpy(regs, sample->before, sizeof(int) * REGS);
|
||
|
instr_interpret(regs, &instr);
|
||
|
if (memcmp(regs, sample->after, sizeof(int) * REGS) == 0) pass++;
|
||
|
}
|
||
|
|
||
|
if (pass >= 3) result++;
|
||
|
}
|
||
|
|
||
|
printf("%d/%d\n", result, samples_len);
|
||
|
|
||
|
g_free(regs);
|
||
|
g_free(samples);
|
||
|
return 0;
|
||
|
}
|