day 21 preliminary refactoring
[aoc_eblake.git] / 2017 / advent18.c
blob905ce2dfba112c7c71b141008c0674ecf760c348
1 #define _GNU_SOURCE 1
2 #include <stdio.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <stdbool.h>
7 #include <ctype.h>
9 typedef struct state state;
10 typedef struct elt elt;
11 struct elt {
12 long long v;
13 elt *next;
15 struct state {
16 long long regs[26];
17 unsigned int pc;
18 elt *head;
19 elt *tail;
20 int sent;
21 int count;
22 } states[2];
24 char *program[50]; // sized based on pre-inspecting file
25 int instr;
27 long long
28 get (state *s, const char *value)
30 if (isalpha(*value))
31 return s->regs[*value - 'a'];
32 return atoi (value);
35 void
36 set (state *s, const char *reg, long long value)
38 s->regs[*reg - 'a'] = value;
39 if (getenv ("DEBUG"))
40 printf (" %s=%lld\n", reg, value);
43 bool
44 run (state *s, int id)
46 elt *e;
47 while (s->pc < instr) {
48 char arg1[10], arg2[10];
49 if (getenv ("DEBUG"))
50 printf ("p%d instr %d at pc %d: %s\n", id, s->count, s->pc,
51 program[s->pc]);
52 sscanf (program[s->pc], "%*s %9s %9s", arg1, arg2);
53 switch ((program[s->pc][0] << 8) + program[s->pc][1]) {
54 case ('s' << 8) + 'n': // snd X
55 e = malloc (sizeof *e);
56 e->v = get (s, arg1);
57 e->next = NULL;
58 if (s->tail)
59 s->tail->next = e;
60 else
61 s->head = e;
62 s->tail = e;
63 s->sent++;
64 break;
65 case ('s' << 8) + 'e': // set X Y
66 set (s, arg1, get (s, arg2));
67 break;
68 case ('a' << 8) + 'd': // add X Y
69 set (s, arg1, get (s, arg1) + get (s, arg2));
70 break;
71 case ('m' << 8) + 'u': // mul X Y
72 set (s, arg1, get (s, arg1) * get (s, arg2));
73 break;
74 case ('m' << 8) + 'o': // mod X Y
75 set (s, arg1, get (s, arg1) % get (s, arg2));
76 break;
77 case ('r' << 8) + 'c': // rcv X
78 if (!states[!id].head)
79 return true;
80 e = states[!id].head;
81 states[!id].head = e->next;
82 if (!e->next)
83 states[!id].tail = NULL;
84 set (s, arg1, e->v);
85 free (e);
86 break;
87 case ('j' << 8) + 'g': // jgz X Y
88 if (get (s, arg1) > 0)
89 s->pc += get (s, arg2) - 1;
90 break;
91 default:
92 return 1;
94 s->count++;
95 s->pc++;
97 return false;
100 int main(int argc, char **argv)
102 char buf[400]; // sized based on pre-inspecting file
103 int nread = fread (buf, 1, sizeof buf, stdin);
104 char *p = buf;
105 while (p < buf + nread) {
106 program[instr++] = p;
107 p = strchr (p, '\n');
108 *p++ = '\0';
110 printf ("program consists of %d instructions\n", instr);
111 states[1].regs['p' - 'a'] = 1;
112 int swap = 0;
113 while ((run (&states[0], 0) + run (&states[1], 1)) &&
114 (states[0].head || states[1].head)) {
115 swap++;
116 printf ("%d+%d operations, %d swaps, %d+%d sent\n", states[0].count,
117 states[1].count, swap, states[0].sent, states[1].sent);
119 printf ("after %d+%d operations and %d swaps, p1 sent %d times\n",
120 states[0].count, states[1].count, swap, states[1].sent);
121 return 0;