cleanup
[advent21.git] / 16a.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <stdint.h>
5
6 char *hex2bin[] =
7 { ['0'] = "0000", ['1'] = "0001", ['2'] = "0010", ['3'] = "0011"
8 , ['4'] = "0100", ['5'] = "0101", ['6'] = "0110", ['7'] = "0111"
9 , ['8'] = "1000", ['9'] = "1001", ['A'] = "1010", ['B'] = "1011"
10 , ['C'] = "1100", ['D'] = "1101", ['E'] = "1110", ['F'] = "1111"
11 , ['\n'] = "0000"};
12
13 struct stream { int pos; char *buf; };
14
15 int next(struct stream *f)
16 {
17 if (*f->buf == '\0') {
18 int c = getchar();
19 if (c == EOF) {
20 printf("EOF\n");
21 exit(1);
22 }
23 f->buf = hex2bin[c];
24 }
25 int r =*(f->buf++) == '1' ? 1 : 0;
26 f->pos++;
27 return r;
28 }
29
30 int bin2int(struct stream *f, int n)
31 {
32 int r = 0;
33 for (int i = 0; i<n; i++)
34 r = 2*r+next(f);
35 return r;
36 }
37
38 int parse_packet(struct stream *f)
39 {
40 int packetversion = bin2int(f, 3);
41 int packettype = bin2int(f, 3);
42
43 switch (packettype) {
44 //Literal value
45 case 4: {
46 int num = 0;
47 while (next(f) == 1) {
48 num = num*16+bin2int(f, 4);
49 }
50 num = num*16+bin2int(f, 4);
51 break;
52 }
53 default: {
54 int lengthtypeid = next(f);
55
56 //length is 15
57 if (lengthtypeid == 0) {
58 int lengthsubpackets = bin2int(f, 15);
59 int oldpos = f->pos;
60
61 while (f->pos - oldpos < lengthsubpackets)
62 packetversion += parse_packet(f);
63 } else {
64 int numsubpackets = bin2int(f, 11);
65 for (int i = 0; i<numsubpackets; i++)
66 packetversion += parse_packet(f);
67 }
68 break;
69 }}
70 return packetversion;
71 }
72
73 int main()
74 {
75 struct stream f = {.pos=0, .buf=""};
76 printf("r: %d\n", parse_packet(&f));
77 }