From d1221ab086cae554ba44fce3801117c76a358af7 Mon Sep 17 00:00:00 2001 From: Bruno Raoult Date: Thu, 22 Sep 2022 10:11:24 +0200 Subject: [PATCH] 2019 day 5: add examples from day 2, add _stringify in br.h --- 2019/day05/EXAMPLE.txt | 2 +- 2019/day05/EXAMPLE2.txt | 2 +- 2019/day05/EXAMPLE3.txt | 1 + 2019/day05/EXAMPLE4.txt | 1 + 2019/day05/EXAMPLE5.txt | 1 + 2019/day05/EXAMPLE6.txt | 1 + 2019/day05/EXAMPLE7.txt | 1 + 2019/day05/EXAMPLE8.txt | 1 + 2019/day05/aoc-c.c | 338 ++++++++++++++++++++++++++++++++++++---- 2019/include/br.h | 7 + 10 files changed, 320 insertions(+), 35 deletions(-) create mode 100644 2019/day05/EXAMPLE3.txt create mode 100644 2019/day05/EXAMPLE4.txt create mode 100644 2019/day05/EXAMPLE5.txt create mode 100644 2019/day05/EXAMPLE6.txt create mode 100644 2019/day05/EXAMPLE7.txt create mode 100644 2019/day05/EXAMPLE8.txt diff --git a/2019/day05/EXAMPLE.txt b/2019/day05/EXAMPLE.txt index 8d109b0..2912131 100644 --- a/2019/day05/EXAMPLE.txt +++ b/2019/day05/EXAMPLE.txt @@ -1 +1 @@ -1002,4,3,4 +1,9,10,3,2,3,11,0,99,30,40,50 diff --git a/2019/day05/EXAMPLE2.txt b/2019/day05/EXAMPLE2.txt index 4c34a69..a2389ec 100644 --- a/2019/day05/EXAMPLE2.txt +++ b/2019/day05/EXAMPLE2.txt @@ -1 +1 @@ -1101,100,-1,4,0 +1,0,0,0,99 diff --git a/2019/day05/EXAMPLE3.txt b/2019/day05/EXAMPLE3.txt new file mode 100644 index 0000000..e795b14 --- /dev/null +++ b/2019/day05/EXAMPLE3.txt @@ -0,0 +1 @@ +2,3,0,3,99 diff --git a/2019/day05/EXAMPLE4.txt b/2019/day05/EXAMPLE4.txt new file mode 100644 index 0000000..89e8255 --- /dev/null +++ b/2019/day05/EXAMPLE4.txt @@ -0,0 +1 @@ +2,4,4,5,99,0 diff --git a/2019/day05/EXAMPLE5.txt b/2019/day05/EXAMPLE5.txt new file mode 100644 index 0000000..f4b112c --- /dev/null +++ b/2019/day05/EXAMPLE5.txt @@ -0,0 +1 @@ +1,1,1,4,99,5,6,0,99 diff --git a/2019/day05/EXAMPLE6.txt b/2019/day05/EXAMPLE6.txt new file mode 100644 index 0000000..f69dc4d --- /dev/null +++ b/2019/day05/EXAMPLE6.txt @@ -0,0 +1 @@ +3,0,4,0,99 diff --git a/2019/day05/EXAMPLE7.txt b/2019/day05/EXAMPLE7.txt new file mode 100644 index 0000000..6b88b4a --- /dev/null +++ b/2019/day05/EXAMPLE7.txt @@ -0,0 +1 @@ +1002,4,3,4,33 diff --git a/2019/day05/EXAMPLE8.txt b/2019/day05/EXAMPLE8.txt new file mode 100644 index 0000000..4c34a69 --- /dev/null +++ b/2019/day05/EXAMPLE8.txt @@ -0,0 +1 @@ +1101,100,-1,4,0 diff --git a/2019/day05/aoc-c.c b/2019/day05/aoc-c.c index 7223c35..d80e87d 100644 --- a/2019/day05/aoc-c.c +++ b/2019/day05/aoc-c.c @@ -15,49 +15,243 @@ #include #include +#include "br.h" +#include "bits.h" #include "debug.h" +struct { + int cur; + int length; + int val[10]; +} input; + +typedef enum { + VAL = 1, /* param is direct value */ + PTR = 0 /* param is indirect value */ +} param_t; + typedef enum { ADD = 1, MUL = 2, - RET = 99 + INP = 3, + OUT = 4, + HLT = 99 } opcode_t; +/** + * ops - array of op-codes mnemoand number of parameters + * @len: number of parameters + * @mnemo: op mnemo + */ +static struct { + opcode_t op; + u8 len; + char *mnemo; +} ops[] = { + [ADD] = { ADD, 3, __stringify(ADD) }, + [MUL] = { MUL, 3, __stringify(MUL) }, + [INP] = { INP, 1, __stringify(INP) }, + [OUT] = { OUT, 1, __stringify(OUT) }, + [HLT] = { HLT, 0, __stringify(HLT) } +}; + +static void print_avail_instr() +{ + log_f(3, "ops size: %zu\n", ARRAY_SIZE(ops)); + for (uint i = 0; i < ARRAY_SIZE(ops); ++i) { + if (ops[i].op) + log(3, "%02u [%3s] %2d\n", i, ops[i].mnemo, ops[i].len); + } +} + +union mem { + struct { + u8 op: 8; + u8 nargs; + u8 flags: 8; + }; + uint instr; + int param; + int *ind; +}; + #define MAXOPS 1024 struct program { int length; /* total program length */ int cur; /* current position */ - int ops[MAXOPS]; /* should really be dynamic */ + union mem mem[MAXOPS]; /* should really be dynamic */ }; -#define OP(p) ((p)->ops + (p)->cur) +static int _flag_pow10[] = {1, 100, 1000, 10000}; +#define OP(p, n) ((p->mem[n].instr) % 100) +#define MODE(p, n, i) (((p->mem[n].instr) / _flag_pow10[i]) % 10) -#define A1(p) ((p)->ops + *((p)->ops + (p)->cur + 1)) -#define A2(p) ((p)->ops + *((p)->ops + (p)->cur + 2)) -#define A3(p) ((p)->ops + *((p)->ops + (p)->cur + 3)) - -static int run(struct program *prog) +static union mem *parse_opcode(struct program *p, int pos, union mem *res) { + u8 op = p->mem[pos].instr % 100; + int flags = p->mem[pos].instr / 100; + int nargs = ops[op].len; + + log_f(5, "opcode=%02d, flags=%03d", op, flags); + if (!ops[op].op) { + log(5, "fatal: unknown opcode %d at [%03d]\n", op, pos); + return NULL; + } + res->op = op; + res->nargs = nargs; + res->flags = 0; + for (int i = 0; i < nargs; ++i) { + res->flags |= flags % 10 << i; + log(3, " flag(0)=%d %d\n", flags % 10 << i, MODE(p, pos, i + 1)); + flags /= 10; + (res + i + 1)->param = p->mem[pos + i + 1].param; + log(5, "\t%2d = %d\n", i+1, (res + 1)->param); + } + log_f(3, "%d %c%c%c %d %d %d\n", res->op, + res->flags&4, res->flags&2, res->flags&1, (res + 1)->param, + (res + 2)->param, (res + 3)->param); + return res; +} + +static int print_opcode(struct program *p, int pos) +{ + //union mem mem[10], *instr; + int op = OP(p, pos); + if (ops[op].op) { + int nargs = ops[op].len; + //instr->nargs; + //int flags = instr->flags; + + log(3, "%03d [%2d][%3s]\t", pos, op, ops[op].mnemo); + for (int i = 1; i <= nargs; ++i) { + int direct = p->mem[pos + i].param; + if (i > 1) + log(3, ", "); + if (i < 3 && !MODE(p, pos, i)) { + log(3, "*[%d]=", direct); + int val = p->mem[direct].param; + log(3, "%d", val); + } else { + log(3, "%d", direct); + } + } + log(3, "\n"); + return nargs; + } else { + log(3, "%03d \t", pos); + log(3, "%d\n", p->mem[pos].param); + return 0; + } + //p->mem[pos].op, ops[p->mem[pos].op]); + //log_f(3, "program size: %d\n", p->length); + //for (uint i = 0; i < ARRAY_SIZE(ops); ++i) { + //if (ops[i].len) + //} +} + +static void print_program_codes(struct program *p) +{ + log(3, "program codes: length=%d\n", p->length); + for (int i = 0; i < p->length; ++i) + log(3, "%d ", p->mem[i].param); + log(3, "\n"); +} + +static void print_program(struct program *p) +{ + print_program_codes(p); + log(3, "program: length=%d\n", p->length); + for (int i = 0; i < p->length; ++i) { + i += print_opcode(p, i); + } +} + +//#define INDIRECT(p, n) (*(&p->mem[0].param + p->mem[n].param)) +#define INDIRECT(p, n) (p->mem[n].param) +//#define INDIRECT(p, n) (p->mem[_INDIRECT(p, n)].param) + +//#define OP(p) ((p)->ops + (p)->cur) + +//#define A1(p) ((p)->ops + *((p)->ops + (p)->cur + 1)) +//#define A2(p) ((p)->ops + *((p)->ops + (p)->cur + 2)) +//#define A3(p) ((p)->ops + *((p)->ops + (p)->cur + 3)) + +/** + */ +static int peek(struct program *p, int pos, int arg) +{ + int flag = MODE(p, pos, arg); + int ret = p->mem[pos + arg].param; + if (flag) { + log_f(3, "getting direct value "); + } else { + log_f(3, "getting indirect (%d) value ", ret); + ret = p->mem[ret].param; + } + log(3, "%d\n", ret); + return ret; +} + +static int poke(struct program *p, int pos, int arg, int val) +{ + int addr = p->mem[pos + arg].param; + log_f(3, "val(%d)=%d\n", pos+arg, addr); + //print_program(p); + log_f(3, "poking %d at %d+%d=%d\n", val, pos, arg, addr); + p->mem[addr].param = val; + print_program(p); + return val; +} + +static int run(struct program *p) +{ + //union mem mem[10], *instr; while (1) { - opcode_t opcode = *OP(prog); - switch (opcode) { + int op = OP(p, p->cur); + int n1, n2; + log_f(3, "cur position=%d\n", p->cur); + if (!(ops[op].op)) { + log(3, "PANIC: illegal instruction %d.\n", op); + return -1; + } + log(3, "%d, cur=%d len=%d, %d, %d, %d\n", op, p->cur, + ops[op].len, p->mem[p->cur+1].instr, + p->mem[p->cur+2].instr, p->mem[p->cur+3].instr); + + switch (op) { case ADD: - *A3(prog) = *A1(prog) + *A2(prog); + log(3, "ADD\n"); + n1 = peek(p, p->cur, 1); + n2 = peek(p, p->cur, 2); + poke(p, p->cur, 3, n1 + n2); + //*A3(p) = *A1(p) + *A2(p); break; case MUL: - *A3(prog) = *A1(prog) * *A2(prog); + log(3, "MUL\n"); + n1 = peek(p, p->cur, 1); + n2 = peek(p, p->cur, 2); + poke(p, p->cur, 3, n1 * n2); + //*A3(prog) = *A1(prog) * *A2(prog); + break; + case HLT: + return p->mem[0].param; + case INP: + poke(p, p->cur, 1, input.val[input.cur++]); + break; + case OUT: + printf("***OUT: %d\n", peek(p, p->cur, 0)); break; - case RET: - return prog->ops[0]; default: - fprintf(stderr, "wrong opcode %d at %d.\n", opcode, prog->cur); + fprintf(stderr, "unknown error\n"); exit (1); } - prog->cur += 4; + p->cur += ops[op].len + 1; + log_f(3, "+++ cur position=%d\n", p->cur); } return -1; } + static struct program *parse() { size_t alloc = 0; @@ -83,7 +277,7 @@ static struct program *parse() goto freebuf; } input=atoi(token); - prog->ops[prog->length++] = input; + prog->mem[prog->length++].param = input; } freebuf: free(buf); @@ -91,28 +285,95 @@ end: return prog; } +/* + * size_t alloc = 0; + * ssize_t buflen; + * char *buf = NULL, *token; + * union mem input; + * u8 opcode, flags, nargs; + * struct program *prog = NULL; + * + * if ((buflen = getline(&buf, &alloc, stdin)) <= 0) { + * fprintf(stderr, "error reading file.\n"); + * goto end; + * } + * + * if (!(prog = calloc(1, sizeof(struct program)))) { + * fprintf(stderr, "cannot allocate program.\n"); + * goto freebuf; + * } + * for (token = strtok(buf, ","); token; token = strtok(NULL, ",")) { + * if (prog->length >= MAXOPS - 1) { + * fprintf(stderr, "overflow !\n"); + * free(prog); + * prog = NULL; + * goto freebuf; + * } + * input.param = atoi(token); + * /\* we get opcode and parameters types *\/ + * opcode = input.param % 100; + * flags = input.param / 100; + * //log(3, "opcode=%02d, flags=%03d", opcode, flags); + * if (!ops[opcode].op) { + * log(3, "fatal: unknown opcode %d\n", opcode); + * exit(1); + * } + * prog->mem[prog->length].op = opcode; + * /\* get op arguments *\/ + * if ((nargs = ops[opcode].len)) { + * log(3, "opcode=%02d, flags=%03d\n", opcode, flags); + * for (int i = 0; i < nargs; ++i) { + * if (!(token = strtok(NULL, ","))) { + * fprintf(stderr, "overflow !\n"); + * free(prog); + * prog = NULL; + * goto freebuf; + * } + * prog->mem[prog->length].flags |= flags % 10 << i; + * flags /= 10; + * prog->mem[prog->length + 1 + i].param = atoi(token); + * log(3, "\t%2d = %d\n", i+1, atoi(token)); + * } + * } + * prog->length += nargs +1; + * //if (prog->length >= MAXOPS - 1) { + * // if () + * //prog->ops[prog->length++] = input; + * } + * freebuf: + * free(buf); + * end: + * return prog; + * } + */ + static int part1(struct program *p) { - p->ops[1] = 12; - p->ops[2] = 2; + input.val[input.length++] = 1; + run(p); +// p->ops[1] = 12; +// p->ops[2] = 2; - return run(p); + return p->length; } static int part2(struct program *p) { - struct program work; - - for (int noun = 0; noun < 100; ++noun) { - for (int verb = 0; verb < 100; ++verb) { - work = *p; - work.ops[1] = noun; - work.ops[2] = verb; - if (run(&work) == 19690720) - return noun * 100 + verb; - } - } - return -1; + /* + * struct program work; + * + * for (int noun = 0; noun < 100; ++noun) { + * for (int verb = 0; verb < 100; ++verb) { + * work = *p; + * work.ops[1] = noun; + * work.ops[2] = verb; + * if (run(&work) == 19690720) + * return noun * 100 + verb; + * } + * } + * return -1; + */ + return p->length; } static int usage(char *prg) @@ -143,8 +404,19 @@ int main(int ac, char **av) if (optind < ac) return usage(*av); + //print_avail_instr(); p = parse(); + print_program(p); + //return 0; + //union mem mem[10], *instr; + //instr = parse_opcode(p, p->cur, mem); + //peek(p, mem, 0); + //exit(0); + part1(p); + print_program_codes(p); + printf("mem[0] = %d\n", p->mem[0].param); + exit(0); printf("%s : res=%d\n", *av, part == 1? part1(p): part2(p)); - free(p); + //free(p); exit (0); } diff --git a/2019/include/br.h b/2019/include/br.h index ea346f9..30110e6 100644 --- a/2019/include/br.h +++ b/2019/include/br.h @@ -18,6 +18,13 @@ #ifndef _BR_H #define _BR_H +/* Indirect stringification. Doing two levels allows the parameter to be a + * macro itself. For example, compile with -DFOO=bar, __stringify(FOO) + * converts to "bar". + */ +#define __stringify_1(x...) #x +#define __stringify(x...) __stringify_1(x) + /* generate a (maybe) unique id. */ #define ___PASTE(x, y) x##y