--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+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"};
+
+struct stream {
+       int pos;
+       char *buf;
+};
+
+int next(struct stream *f)
+{
+       if (*f->buf == '\0') {
+               int c = getchar();
+               if (c == EOF) {
+                       printf("EOF\n");
+                       exit(1);
+               }
+               f->buf = hex2bin[c];
+       }
+       int r =*f->buf == '1' ? 1 : 0;
+       f->buf++;
+       f->pos++;
+       return r;
+}
+
+int bin2int(struct stream *f, int n)
+{
+       int r = 0;
+       for (int i = 0; i<n; i++)
+               r = 2*r+next(f);
+       return r;
+}
+
+int parse_packet(struct stream *f)
+{
+       int packetversion = bin2int(f, 3);
+       int packettype = bin2int(f, 3);
+
+       switch (packettype) {
+       //Literal value
+       case 4: {
+               int num = 0;
+               while (next(f) == 1) {
+                       num = num*16+bin2int(f, 4);
+               }
+               num = num*16+bin2int(f, 4);
+               break;
+       }
+       default: {
+               int lengthtypeid = next(f);
+
+               //length is 15
+               if (lengthtypeid == 0) {
+                       int lengthsubpackets = bin2int(f, 15);
+                       int oldpos = f->pos;
+
+                       while (f->pos - oldpos < lengthsubpackets)
+                               packetversion += parse_packet(f);
+               } else {
+                       int numsubpackets = bin2int(f, 11);
+                       for (int i = 0; i<numsubpackets; i++)
+                               packetversion += parse_packet(f);
+               }
+               break;
+       }}
+       return packetversion;
+}
+
+int main()
+{
+       struct stream f = {.pos=0, .buf=""};
+
+       int r = parse_packet(&f);
+       printf("r: %d\n", r);
+}
 
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+
+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"};
+
+struct stream { int pos; char *buf; };
+
+int next(struct stream *f)
+{
+       int r;
+       if (*f->buf == '\0') {
+               if ((r = getchar()) == EOF) {
+                       printf("EOF\n");
+                       exit(1);
+               }
+               f->buf = hex2bin[r];
+       }
+       r =*(f->buf++) == '1' ? 1 : 0;
+       f->pos++;
+       return r;
+}
+
+unsigned long bin2int(struct stream *f, int n)
+{
+       unsigned long r = 0;
+       for (int i = 0; i<n; i++)
+               r = 2*r+next(f);
+       return r;
+}
+
+unsigned long parse_packet(struct stream *f)
+{
+       int packetversion  __attribute__((unused)) = bin2int(f, 3);
+       int packettype = bin2int(f, 3);
+       unsigned long result = 0;
+
+       //literal
+       if (packettype == 4) {
+               while (next(f) == 1)
+                       result = result*16+bin2int(f, 4);
+               result = result*16+bin2int(f, 4);
+       //operator
+       } else {
+               int lengthtypeid = next(f);
+               unsigned long packets[100] = {0};
+               int npackets = 0;
+
+               //number of bits
+               if (lengthtypeid == 0) {
+                       int lengthsubpackets = bin2int(f, 15);
+                       int oldpos = f->pos;
+                       while (f->pos - oldpos < lengthsubpackets)
+                               packets[npackets++] = parse_packet(f);
+               //number of packets
+               } else {
+                       npackets = bin2int(f, 11);
+                       for (int i = 0; i<npackets; i++)
+                               packets[i] = parse_packet(f);
+               }
+
+               //sum
+               if (packettype == 0) {
+                       for (int i = 0; i<npackets; i++)
+                               result += packets[i];
+               //product
+               } else if (packettype == 1) {
+                       result = 1;
+                       for (int i = 0; i<npackets; i++)
+                               result *= packets[i];
+               //minimum
+               } else if (packettype == 2) {
+                       result = ULONG_MAX;
+                       for (int i = 0; i<npackets; i++)
+                               result = packets[i] < result ? packets[i] : result;
+               //maximum
+               } else if (packettype == 3) {
+                       result = 0;
+                       for (int i = 0; i<npackets; i++)
+                               result = packets[i] > result ? packets[i] : result;
+               //greater than
+               } else if (packettype == 5) {
+                       result = packets[0] > packets[1];
+               //less than
+               } else if (packettype == 6) {
+                       result = packets[0] < packets[1];
+               //equal to
+               } else if (packettype == 7) {
+                       result = packets[0] == packets[1];
+               //unknown
+               } else {
+                       fprintf(stderr, "unknown operator: %d\n", packettype);
+                       exit(1);
+               }
+       }
+       return result;
+}
+
+int main()
+{
+       struct stream f = {.pos=0, .buf=""};
+       printf("r: %lu\n", parse_packet(&f));
+}