--- /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));
+}