diff --git a/2019/RESULTS.txt b/2019/RESULTS.txt index b88f369..9e837f2 100644 --- a/2019/RESULTS.txt +++ b/2019/RESULTS.txt @@ -116,3 +116,17 @@ aoc-c : res=2250 aoc-c : res=0 time: 0:00.00 real, 0.00 user, 0.00 sys context-switch: 0+1, page-faults: 0+90 + +========================================= +================= day09 ================= +========================================= + ++++++++++++++++++ part 1 +aoc-c : res=2682107844 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+92 + ++++++++++++++++++ part 2 +aoc-c : res=34738 + time: 0:00.01 real, 0.01 user, 0.00 sys + context-switch: 1+1, page-faults: 0+95 diff --git a/2019/day09/README.org b/2019/day09/README.org index 1d28a35..401cbb7 100644 --- a/2019/day09/README.org +++ b/2019/day09/README.org @@ -72,10 +72,23 @@ report no malfunctioning opcodes when run in test mode; it should only output a single value, the BOOST keycode. /What BOOST keycode does it produce?/ -To begin, [[file:9/input][get your puzzle input]]. +Your puzzle answer was =2682107844=. -Answer: +** --- Part Two --- +/You now have a complete Intcode computer./ -You can also [Shareon -[[https://twitter.com/intent/tweet?text=%22Sensor+Boost%22+%2D+Day+9+%2D+Advent+of+Code+2019&url=https%3A%2F%2Fadventofcode%2Ecom%2F2019%2Fday%2F9&related=ericwastl&hashtags=AdventOfCode][Twitter]] -[[javascript:void(0);][Mastodon]]] this puzzle. +Finally, you can lock on to the Ceres distress signal! You just need to +boost your sensors using the BOOST program. + +The program runs in sensor boost mode by providing the input instruction +the value =2=. Once run, it will boost the sensors automatically, but it +might take a few seconds to complete the operation on slower hardware. +In sensor boost mode, the program will output a single value: /the +coordinates of the distress signal/. + +Run the BOOST program in sensor boost mode. /What are the coordinates of +the distress signal?/ + +Your puzzle answer was =34738=. + +Both parts of this puzzle are complete! They provide two gold stars: ** diff --git a/2019/day09/aoc-c.c b/2019/day09/aoc-c.c index f749aa2..3bec731 100644 --- a/2019/day09/aoc-c.c +++ b/2019/day09/aoc-c.c @@ -21,6 +21,8 @@ #include "list.h" #include "pool.h" +#define _unused __attribute__((unused)) + /* operators codes */ typedef enum { @@ -42,17 +44,18 @@ typedef struct { u8 length; } ops_t; -typedef struct input { +typedef struct io { s64 val; struct list_head list; -} input_t; +} io_t; -#define MAXOPS 1024 +#define MAXOPS 2048 typedef struct { - int length; /* total program length */ - int cur; /* current instruction */ - int rel; /* current relative memory */ + s64 length; /* total program length */ + s64 cur; /* current instruction */ + s64 rel; /* current relative memory */ struct list_head input; /* process input queue */ + struct list_head output; /* process output queue */ s64 mem [MAXOPS]; /* should really be dynamic */ } program_t; @@ -87,109 +90,83 @@ static inline param_t paramtype(program_t *prg, int addr, int param) #define ISDIRECT(p, n, i) ((((p->mem[n]) / _flag_pow10[i]) % 10) == 1) #define DIRECT(p, i) ((p)->mem[i]) #define INDIRECT(p, i) (DIRECT(p, DIRECT(p, i))) +#define RELATIVE(p, i) (DIRECT(p , p->rel + DIRECT(p, i))) -static inline s64 peek(program_t *prg, int cur, int param) +static inline s64 peek(program_t *prg, s64 cur, s64 param) { - param_t partype = paramtype(prg, cur, param); - //printf("partype=%d\n", partype); - switch(partype) { + switch(paramtype(prg, cur, param)) { case DIR: return DIRECT(prg, cur + param); case IND: return INDIRECT(prg, cur + param); case REL: - return INDIRECT(prg, cur + prg->rel + param); + return RELATIVE(prg, cur + param); } return 0; /* not reached */ } static inline void poke(program_t *prg, int cur, int param, s64 val) { - - param_t partype = paramtype(prg, cur, param); - //printf("partype=%d\n", partype); - switch(partype) { - case DIR: - printf("should not happen here\n"); - break; - // DIRECT(prg, cur + param); + switch(paramtype(prg, cur, param)) { case IND: INDIRECT(prg, cur + param) = val; + case DIR: /* never happens */ break; case REL: - INDIRECT(prg, cur + prg->rel + param) = val; + RELATIVE(prg, cur + param) = val; } } -//#define peek(p, n, i) (ISDIRECT(p, n, i)? DIRECT(p, n + i): INDIRECT(p, n + i)) -/* -#define poke(p, n, i, val) do { \ - INDIRECT(p, n + i) = val; } \ - while (0) -*/ +static pool_t *pool_io; -static pool_t *pool_input; -static __always_inline s64 prg_add_input(program_t *prg, s64 in) +static __always_inline int prg_add_input(program_t *prg, s64 in) { - input_t *input = pool_get(pool_input); + io_t *input = pool_get(pool_io); input->val = in; list_add_tail(&input->list, &prg->input); return in; } -static __always_inline s64 prg_get_input(program_t *prg, s64 *out) +static __always_inline s64 prg_add_output(program_t *prg, s64 out) { - input_t *input = list_first_entry_or_null(&prg->input, input_t, list); + io_t *output = pool_get(pool_io); + output->val = out; + list_add_tail(&output->list, &prg->output); + return out; +} + +static __always_inline int prg_get_input(program_t *prg, s64 *in) +{ + io_t *input = list_first_entry_or_null(&prg->input, io_t, list); if (!input) return 0; - *out = input->val; + *in = input->val; list_del(&input->list); - pool_add(pool_input, input); + pool_add(pool_io, input); return 1; } -/** - * permute - get next permutation of an array of integers - * @len: length of array - * @array: address of array - * - * Algorithm: lexicographic permutations - * https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order - * Before the initial call, the array must be sorted (e.g. 0 2 3 5) - * - * Return: 1 if next permutation was found, 0 if no more permutation. - * - */ -static int permute_next(int len, int *array) +static __always_inline _unused int prg_get_output(program_t *prg, s64 *out) { - int k, l; - - /* 1. Find the largest index k such that a[k] < a[k + 1] */ - for (k = len - 2; k >= 0 && array[k] >= array[k + 1]; k--) - ; - /* No more permutations */ - if (k < 0) + io_t *output = list_first_entry_or_null(&prg->output, io_t, list); + if (!output) return 0; - /* 2. Find the largest index l greater than k such that a[k] < a[l] */ - for (l = len - 1; array[l] <= array[k]; l--) - ; - /* 3. Swap the value of a[k] with that of a[l] */ - swap(array[k], array[l]); - /* 4. Reverse sequence from a[k + 1] up to the final element */ - for (l = len - 1, k++; k < l; k++, l--) - swap(array[k], array[l]); + *out = output->val; + list_del(&output->list); + pool_add(pool_io, output); return 1; } static s64 run(program_t *p, int *end) { - s64 out = -1, input; + s64 out = -1, input, tmp; + while (1) { int cur = p->cur; opcode_t op = getop(p, p->cur); if (!(ops[op].op)) { - fprintf(stderr, "PANIC: illegal instruction %d at %d.\n", op, p->cur); + fprintf(stderr, "PANIC: illegal instruction %d at %ld.\n", op, p->cur); return -1; } switch (op) { @@ -211,6 +188,7 @@ static s64 run(program_t *p, int *end) break; case OUT: out = peek(p, p->cur, 1); + prg_add_output(p, out); break; case JMP_T: if (peek(p, p->cur, 1)) @@ -253,19 +231,14 @@ static int usage(char *prg) int main(int ac, char **av) { - int phase1[] = {0, 1, 2, 3, 4}, phase2[] = {5, 6, 7, 8, 9}, *phase; - int opt, max = 0, part = 1; - program_t p = { 0 }, prg[5]; + int opt, end = 0, part = 1; + program_t p = { 0 }; - while ((opt = getopt(ac, av, "d:p:o:")) != -1) { + while ((opt = getopt(ac, av, "d:p:")) != -1) { switch (opt) { case 'd': debug_level_set(atoi(optarg)); break; - case 'o': - for (ulong i = 0; i < strlen(optarg); ++i) - phase1[i] = optarg[i] - '0'; - break; case 'p': /* 1 or 2 */ part = atoi(optarg); if (part < 1 || part > 2) @@ -276,39 +249,17 @@ int main(int ac, char **av) } } - pool_input = pool_create("input", 128, sizeof(input_t)); + pool_io = pool_create("i/o", 128, sizeof(io_t)); if (optind < ac) return usage(*av); - phase = part == 1? phase1: phase2; parse(&p); + INIT_LIST_HEAD(&p.input); + INIT_LIST_HEAD(&p.output); + prg_add_input(&p, part); - do { - int out = 0, end = 0; - /* reset programs initial state, and add phase to their input - */ - for (unsigned i = 0; i < ARRAY_SIZE(prg); ++i) { - prg[i] = p; - INIT_LIST_HEAD(&prg[i].input); - prg_add_input(&prg[i], phase[i]); - } - - /* run the 5 processes in order (0, 1, 2, 3, 4, 0, 1, etc...), - * until end flag is set by the process 4 (HLT instruction) - */ - while (!end) { - for (int i = 0; i < 5; ++i) { - /* add last process output in current process input queue - */ - prg_add_input(&prg[i], out); - out = run(&prg[i], &end); - } - } - max = max(max, out); - } while (permute_next(5, phase)); - - printf("%s : res=%d\n", *av, max); - pool_destroy(pool_input); + printf("%s : res=%ld\n", *av, run(&p, &end)); + pool_destroy(pool_io); exit(0); }