diff --git a/2019/RESULTS.txt b/2019/RESULTS.txt index 454b27f..9b9ad50 100644 --- a/2019/RESULTS.txt +++ b/2019/RESULTS.txt @@ -82,3 +82,17 @@ aoc-c : res=453028 aoc-c : res=562 time: 0:00.00 real, 0.00 user, 0.00 sys context-switch: 0+1, page-faults: 0+417 + +========================================= +================= day07 ================= +========================================= + ++++++++++++++++++ part 1 +aoc-c : res=65464 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+94 + ++++++++++++++++++ part 2 +aoc-c : res=1518124 + time: 0:00.00 real, 0.00 user, 0.00 sys + context-switch: 0+1, page-faults: 0+94 diff --git a/2019/day07/README.html b/2019/day07/README.html deleted file mode 100644 index 1c81416..0000000 --- a/2019/day07/README.html +++ /dev/null @@ -1,145 +0,0 @@ - - - - -Day 7 - Advent of Code 2019 - - - - - - - - -

Advent of Code

Bruno Raoult 12*

      /^2019$/

- - - -
-

--- Day 7: Amplification Circuit ---

Based on the navigational maps, you're going to need to send more power to your ship's thrusters to reach Santa in time. To do this, you'll need to configure a series of amplifiers already installed on the ship.

-

There are five amplifiers connected in series; each one receives an input signal and produces an output signal. They are connected such that the first amplifier's output leads to the second amplifier's input, the second amplifier's output leads to the third amplifier's input, and so on. The first amplifier's input value is 0, and the last amplifier's output leads to your ship's thrusters.

-
    O-------O  O-------O  O-------O  O-------O  O-------O
-0 ->| Amp A |->| Amp B |->| Amp C |->| Amp D |->| Amp E |-> (to thrusters)
-    O-------O  O-------O  O-------O  O-------O  O-------O
-
-

The Elves have sent you some Amplifier Controller Software (your puzzle input), a program that should run on your existing Intcode computer. Each amplifier will need to run a copy of the program.

-

When a copy of the program starts running on an amplifier, it will first use an input instruction to ask the amplifier for its current phase setting (an integer from 0 to 4). Each phase setting is used exactly once, but the Elves can't remember which amplifier needs which phase setting.

-

The program will then call another input instruction to get the amplifier's input signal, compute the correct output signal, and supply it back to the amplifier with an output instruction. (If the amplifier has not yet received an input signal, it waits until one arrives.)

-

Your job is to find the largest output signal that can be sent to the thrusters by trying every possible combination of phase settings on the amplifiers. Make sure that memory is not shared or reused between copies of the program.

-

For example, suppose you want to try the phase setting sequence 3,1,2,4,0, which would mean setting amplifier A to phase setting 3, amplifier B to setting 1, C to 2, D to 4, and E to 0. Then, you could determine the output signal that gets sent from amplifier E to the thrusters with the following steps:

- -

The final output signal from amplifier E would be sent to the thrusters. However, this phase setting sequence may not have been the best one; another sequence might have sent a higher signal to the thrusters.

-

Here are some example programs:

- -

Try every combination of phase settings on the amplifiers. What is the highest signal that can be sent to the thrusters?

-
-

To begin, get your puzzle input.

-

Answer:

-

You can also this puzzle.

-
- - - - - - \ No newline at end of file diff --git a/2019/day07/aoc-c.c b/2019/day07/aoc-c.c index 3100aaa..fd0b4b1 100644 --- a/2019/day07/aoc-c.c +++ b/2019/day07/aoc-c.c @@ -21,26 +21,24 @@ #include "list.h" #include "pool.h" +/* operators codes + */ typedef enum { - ADD = 1, MUL = 2, - INP = 3, OUT = 4, - JMP_T = 5, JMP_F = 6, - SET_LT = 7, SET_EQ = 8, - HLT = 99 + ADD = 1, MUL = 2, /* CALC: add and mult */ + INP = 3, OUT = 4, /* I/O: input and output value */ + JMP_T = 5, JMP_F = 6, /* JUMPS: jump if true / if false */ + SET_LT = 7, SET_EQ = 8, /* COND SETS: set if true/false */ + HLT = 99 /* HALT */ } opcode_t; /** * ops - array of op-codes, mnemo, and number of parameters - * @op: An integer, the opcode - * @nargs: Opcode number of parameters (unused) - * @jump: Next instruction (usually @nargs + 1) - * @mnemo: Opcode mnemo (unused, for debug) + * @op: An integer, the opcode + * @length: Next instruction offset */ typedef struct { int op; - u8 nargs; - u8 jump; - char *mnemo; + u8 length; } ops_t; typedef struct input { @@ -48,26 +46,20 @@ typedef struct input { struct list_head list; } input_t; - #define MAXOPS 1024 typedef struct { int length; /* total program length */ int cur; /* current position */ - struct list_head input; - //int input[MAXINPUT]; /* input */ + struct list_head input; /* process input queue */ int mem [MAXOPS]; /* should really be dynamic */ } program_t; static ops_t ops[] = { - [ADD] = { ADD, 3, 4, __stringify(ADD) }, - [MUL] = { MUL, 3, 4, __stringify(MUL) }, - [INP] = { INP, 1, 2, __stringify(INP) }, - [OUT] = { OUT, 1, 2, __stringify(OUT) }, - [JMP_T] = { JMP_T, 2, 3, __stringify(JMP_T) }, - [JMP_F] = { JMP_F, 2, 3, __stringify(JMP_F) }, - [SET_LT] = { SET_LT, 3, 4, __stringify(SET_LT) }, - [SET_EQ] = { SET_EQ, 3, 4, __stringify(SET_EQ) }, - [HLT] = { HLT, 0, 1, __stringify(HLT) } + [ADD] = { ADD, 4 }, [MUL] = { MUL, 4 }, + [INP] = { INP, 2 }, [OUT] = { OUT, 2 }, + [JMP_T] = { JMP_T, 3 }, [JMP_F] = { JMP_F, 3 }, + [SET_LT] = { SET_LT, 4 }, [SET_EQ] = { SET_EQ, 4 }, + [HLT] = { HLT, 1 } }; @@ -82,51 +74,9 @@ static int _flag_pow10[] = {1, 100, 1000, 10000}; INDIRECT(p, n + i) = val; } \ while (0) -static int print_opcode(program_t *p, int pos) -{ - int op = OP(p, pos); - if (ops[op].op) { - int nargs = ops[op].nargs; - log(3, "%03d [%2d][%6s]\t", pos, op, ops[op].mnemo); - for (int i = 1; i <= nargs; ++i) { - int direct = p->mem[pos + i]; - //p->mem[pos + i].param; - if (i > 1) - log(3, ", "); - if (i < 3 && !ISDIRECT(p, pos, i)) { - log(3, "*[%d]=", direct); - int val = p->mem[direct]; - 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]); - return 0; - } -} -static void print_program_codes(program_t *p) -{ - log(3, "program codes: length=%d\n", p->length); - for (int i = 0; i < p->length; ++i) - log(3, "%d ", p->mem[i]); - log(3, "\n"); -} -static void print_program(program_t *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); - } -} static pool_t *pool_input; -static int prg_add_input(program_t *prg, int in) +static __always_inline int prg_add_input(program_t *prg, int in) { input_t *input = pool_get(pool_input); input->val = in; @@ -134,7 +84,7 @@ static int prg_add_input(program_t *prg, int in) return in; } -static int prg_get_input(program_t *prg, int *out) +static __always_inline int prg_get_input(program_t *prg, int *out) { input_t *input = list_first_entry_or_null(&prg->input, input_t, list); if (!input) @@ -144,15 +94,6 @@ static int prg_get_input(program_t *prg, int *out) pool_add(pool_input, input); return 1; } -static void prg_print_input(program_t *prg, int num) -{ - input_t *cur; - printf("prg[%d].input: ", num); - list_for_each_entry(cur, &prg->input, list) { - printf("%d ", cur->val); - } - printf("\n"); -} /** * permute - get next permutation of an array of integers @@ -187,12 +128,7 @@ static int permute_next(int len, int *array) return 1; } -static void dup_program(program_t *from, program_t *to) -{ - *to = *from; -} - -static int run(int part, program_t *p, int *end) +static int run(program_t *p, int *end) { int out = -1; while (1) { @@ -210,13 +146,14 @@ static int run(int part, program_t *p, int *end) poke(p, p->cur, 3, peek(p, p->cur, 1) * peek(p, p->cur, 2)); break; case INP: - if (prg_get_input(p, &input)) { - printf("op=%d\nINP %d\n", op, input); + if (prg_get_input(p, &input)) poke(p, p->cur, 1, input); - } else { - printf("NO INPUT\n"); - return out; - } + else + /* we need an input which is not yet avalable, so we need + * to put the program in "waiting mode": We stop it (and + * return output value) without setting end flag. + */ + goto sleep; break; case OUT: out = peek(p, p->cur, 1); @@ -237,10 +174,11 @@ static int run(int part, program_t *p, int *end) break; case HLT: *end = 1; + sleep: return out; } if (p->cur == cur) - p->cur += ops[op].jump; + p->cur += ops[op].length; } } @@ -259,7 +197,7 @@ 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, part = 1; + int opt, max = 0, part = 1; program_t p = { 0 }, prg[5]; while ((opt = getopt(ac, av, "d:p:o:")) != -1) { @@ -288,37 +226,32 @@ int main(int ac, char **av) phase = part == 1? phase1: phase2; parse(&p); - print_program(&p); - int out, max = 0, end; + do { - out = 0; + int out = 0, end = 0; + /* reset programs initial state, and add phase to their input + */ for (unsigned i = 0; i < ARRAY_SIZE(prg); ++i) { - printf("creating array %d\n", i); - dup_program(&p, &prg[i]); + prg[i] = p; INIT_LIST_HEAD(&prg[i].input); prg_add_input(&prg[i], phase[i]); } - // while (1) { - end = 0; + /* 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); - prg_print_input(&prg[i], i); - //prg[i].input[prg[i].lastinput++] = phase[i]; - //prg[i].input[prg[i].lastinput++] = out; - printf("running program %d\n", i); - out = run(part, &prg[i], &end); - printf("end program %d out=%d end=%d\n", i, out, end); + out = run(&prg[i], &end); } } - if (out > max) { - max = out; - printf("new max: %c%c%c%c%c out=%d max=%d\n", phase[0] + '0', - phase[1] + '0', phase[2] + '0', phase[3] + '0', phase[4] + '0', - out, max); - } + max = max(max, out); } while (permute_next(5, phase)); + printf("%s : res=%d\n", *av, max); + pool_destroy(pool_input); exit(0); }