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