From 477ed667b1a9bc7f73850f45449666a8907ecaed Mon Sep 17 00:00:00 2001 From: Sebastiano Tronto Date: Wed, 20 Dec 2023 16:32:41 +0100 Subject: Added solution for 20 --- 2023/20/20b.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 2023/20/20b.c (limited to '2023/20/20b.c') diff --git a/2023/20/20b.c b/2023/20/20b.c new file mode 100644 index 0000000..dc0d6b3 --- /dev/null +++ b/2023/20/20b.c @@ -0,0 +1,143 @@ +/* +This one is a bit weird. This program works only for my specific input +(included in this folder). Similarly to number 8, this program outputs +4 numbers and you have to take the lcm of them. + +I solved it this way: +1. First, using a modified version of the code for part one (graph.c), + I printed the graph as a list of adjacency lists. +2. I then went to https://csacademy.com/app/graph_editor and observed + the graph. I noticed that after the button is pressed, the signal + is sent to 4 independent parts of the graph. Each of these parts has + only one entry point and one exit point. The entry points were not + flip-flop nodes. +3. Finally, I implemented the code to check how long it takes for the + graph to go back to the initial state, and I simulated sending a + signal to each of the 4 parts independently. +*/ + +#include +#include +#include +#include +#include + +#define N 100 +#define ischar(c) (c >= 'a' && c <= 'z') + +typedef struct { + int nin, nout, in[N], out[N]; + char name[20], outc[N][20]; + bool isff, ison, reg[N]; +} node_t; + +typedef struct { + int i, n; + struct {int node; bool hi;} elem[500]; +} queue_t; + +char *buf, line[N][N]; +bool rx; +int b, r, n; +node_t m[N]; +queue_t q; + +void add(int v, bool hi) { + q.elem[q.n].node = v; + q.elem[q.n].hi = hi; + q.n++; +} + +void send(int v, bool hi) { + for (int j = 0; j < m[v].nout; j++) { + add(m[v].out[j], hi); + m[m[v].out[j]].reg[v] = hi; + } +} + +int findm(char *name) { + for (int k = 0; k < n; k++) + if (!strcmp(m[k].name, name)) + return k; + return n; +} + +void sig(int node, bool high) { + q.n = q.i = 0; + add(node, high); + while (q.i < q.n) { + int v = q.elem[q.i].node; + bool hi = q.elem[q.i].hi; + q.i++; + + if (v == b) { + send(v, hi); + } else if (m[v].isff) { + if (!hi) + send(v, m[v].ison = !m[v].ison); + } else { + bool allhi = true; + for (int j = 0; j < m[v].nin; j++) + allhi = allhi && m[v].reg[m[v].in[j]]; + send(v, !allhi); + } + } +} + +bool isclean(void) { + for (int i = 0; i < n; i++) { + if (m[i].isff && m[i].ison) + return false; + else + for (int j = 0; j < m[i].nin; j++) + if (m[i].reg[j]) + return false; + } + return true; +} + +int64_t period(int node) { + int64_t npush = 0; + do { + sig(node, false); + npush++; + } while (!isclean()); + return npush; +} + +int main() { + for (n = 0; (buf = fgets(line[n], N, stdin)) != NULL; n++) { + if (ischar(*buf)) b = n; + m[n].isff = *buf == '%'; + if (!ischar(*buf)) buf++; + for (int i = 0; ischar(*buf); m[n].name[i++] = *(buf++)) ; + buf += 4; + for (int i = 0; *buf != '\n'; i++) { + while (!ischar(*buf)) buf++; + for (int j = 0; ischar(*buf); m[n].outc[i][j++] = *(buf++)) ; + } + } + + for (int i = 0; i < n; i++) { + for (int j = 0; m[i].outc[j][0]; j++) { + int k = findm(m[i].outc[j]); + m[i].out[m[i].nout++] = k; + m[k].in[m[k].nin++] = i; + if (k == n) { + for (int k = 0; m[i].outc[j][k]; k++) + m[n].name[k] = m[i].outc[j][k]; + n++; + } + } + } + + for (int i = 0; i < n; i++) + if (!strcmp(m[i].name, "rx")) + r = i; + + printf("%" PRId64 "\n", period(19)); + printf("%" PRId64 "\n", period(33)); + printf("%" PRId64 "\n", period(39)); + printf("%" PRId64 "\n", period(57)); + return 0; +} -- cgit v1.3