diff --git a/aoc2015/P02.cpp b/aoc2015/P02.cpp new file mode 100644 index 0000000..56b70c3 --- /dev/null +++ b/aoc2015/P02.cpp @@ -0,0 +1,11 @@ +// Replace 'x' with ' ' in input. +int main() { + LL answer1 = 0, sides[3], answer2 = 0; + while(cin >> sides[0] >> sides[1] >> sides[2]) { + sort(sides, &(sides[3])); + answer1 += 3*sides[0]*sides[1] + 2*sides[0]*sides[2] + 2*sides[2]*sides[1]; + answer2 += 2*(sides[0]+sides[1]) + sides[0]*sides[1]*sides[2]; + } + cout << "Answer 1: " << answer1 << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2015/P03.cpp b/aoc2015/P03.cpp new file mode 100644 index 0000000..cdeb271 --- /dev/null +++ b/aoc2015/P03.cpp @@ -0,0 +1,30 @@ +int main() { + set seen; + PI p(0,0), q(0,0); + seen.insert(p); + GS(s); + FORUI(s.size()) { + char c = s[i]; + switch(c) { + case '>': + p.XX++; + break; + case '<': + p.XX--; + break; + case '^': + p.YY--; + break; + case 'v': + p.YY++; + break; + default: + die(); + } + if(seen.find(p) == seen.end()) { + seen.insert(p); + } + swap(p,q); // For part 2, include this line. + } + cout << "Answer: " << seen.size() << endl; +} diff --git a/aoc2015/P04.cpp b/aoc2015/P04.cpp new file mode 100644 index 0000000..850344f --- /dev/null +++ b/aoc2015/P04.cpp @@ -0,0 +1,382 @@ +class MD5 { +public: + typedef uint32_t size_type; // must be 32bit + + MD5(); + MD5(const string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + string hexdigest() const; + friend ostream& operator<<(ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// + +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return (x&y) | (~x&z); +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return (x&z) | (y&~z); +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return string(buf); +} + +////////////////////////////// + +ostream& operator<<(ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} + +////////////////////////////// + +string md5(const string str) { + MD5 md5 = MD5(str); + return md5.hexdigest(); +} + +int main() { + GS(s); + + for(LL i = 0; true; i++) { + string t1 = s + to_string(i); + string t2 = md5(t1); + //cout << " Trying " << t1 << " -> " << t2 << endl; + + bool ok = true; + FORJ(6) { // For part 1, use 5. + if(t2[j] != '0') { + ok = false; + break; + } + } + if(ok) { + cout << i << endl; + return 0; + } + } +} diff --git a/aoc2015/P05.cpp b/aoc2015/P05.cpp new file mode 100644 index 0000000..954cb82 --- /dev/null +++ b/aoc2015/P05.cpp @@ -0,0 +1,60 @@ +string naughty[4] = {"ab", "cd", "pq", "xy"}; + +int main() { + int answer1 = 0, answer2 = 0; + string s; + while(cin >> s) { + cout << "Test " << s << endl; + bool ok = true; + FORI(4) { + if(s.find(naughty[i]) != string::npos) { + ok = false; + break; + } + } + if(ok) { + int wow = 0; + FORUI(s.size()) { + char c = s[i]; + if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c =='u') { + wow++; + } + } + if(wow >= 3) { + for(int i = 1; i < (int)s.size(); i++) { + if(s[i] == s[i-1]) { + answer1++; + break; + } + } + } + } + + // Answer 2: + ok = false; + for(int i = 2; i < (int)s.size(); i++) { + if(s[i] == s[i-2]) { + ok = true; + break; + } + } + if(ok) { + ok = false; + for(int i = (int)s.size()-2; i >= 2; i--) { + char c1 = s[i], c2 = s[i+1]; + for(int j = 0; j+2 <= i; j++) { + if(c1 == s[j] && c2 == s[j+1]) { + ok = true; + break; + } + } + if(ok) { + answer2++; + break; + } + } + } // if ok + } + cout << "Answer 1: " << answer1 << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2015/P06.cpp b/aoc2015/P06.cpp new file mode 100644 index 0000000..4b34e36 --- /dev/null +++ b/aoc2015/P06.cpp @@ -0,0 +1,34 @@ +// Replace comma with space in input and remove "turn" +int main() { + string op, s; + PI from, to; + int grid[1000][1000]; + FORI(1000) { + FORJ(1000) { + grid[i][j] = 0; + } + } + while(cin >> op >> from.XX >> from.YY >> s >> to.XX >> to.YY) { + for(int i = from.XX; i <= to.XX; i++) { + for(int j = from.YY; j <= to.YY; j++) { + if(op == "on") { + grid[i][j]++; // 1 for answer 1 + } + else if(op == "off") { + grid[i][j] = max(0, grid[i][j]-1); // 0 for answer 1 + } + else { + grid[i][j] += 2; // !grid[i][j] for answer 1 + } + } + } + + } + LL answer = 0; + FORI(1000) { + FORJ(1000) { + answer += grid[i][j]; + } + } + cout << "Answer: " << answer << endl; +} diff --git a/aoc2015/P07.cpp b/aoc2015/P07.cpp new file mode 100644 index 0000000..04e4f4a --- /dev/null +++ b/aoc2015/P07.cpp @@ -0,0 +1,136 @@ +typedef uint16_t T; + +#define NOT 0 +#define AND 1 +#define OR 2 +#define LSHIFT 3 +#define RSHIFT 4 +#define SET 5 + +struct OP { + string v1, v2, o; // input 1, input 2, output + T t, v3; // type, input 3 +}; +typedef map MAP; + +int main() { + MAP vals; + vector ops; + + // Read input: + string s; + while(cin >> s) { + OP *op = new OP; + if(s == "NOT") { + op->t = NOT; + cin >> op->v1; + op->v2 = op->v1; + cin >> s >> op->o; + } + else { + op->v2 = op->v1 = s; + cin >> s; + if(s == "OR") { + op->t = OR; + cin >> op->v2; + cin >> s >> op->o; + } + else if(s == "AND") { + op->t = AND; + cin >> op->v2; + cin >> s >> op->o; + } + else if(s == "LSHIFT") { + op->t = LSHIFT; + cin >> op->v3; + cin >> s >> op->o; + } + else if(s == "RSHIFT") { + op->t = RSHIFT; + cin >> op->v3; + cin >> s >> op->o; + } + else if(s == "->") { + cin >> op->o; // Right side + if(op->v1[0] < '0' || op->v1[0] > '9') { + cout << " SET " << op->o << " <- " << op->v1 << endl; + op->t = SET; + } + else { + cout << " SET INT " << op->o << " <- " << op->v1 << endl; + vals[op->o] = stoi(op->v1); + continue; + } + } + else { + cerr << "Unknown operator " << s << endl; + die(); + } + } + ops.push_back(op); + } + // Hard coded values: + FORIT(vector, ops) { + OP* op = *it; + if(op->v1[0] >= '0' && op->v1[0] <= '9') { + vals[op->v1] = stoi(op->v1); + } + if(op->v1 != op->v2 && (op->v2[0] >= '0' && op->v2[0] <= '9')) { + vals[op->v2] = stoi(op->v2); + } + } + + while(vals.find("a") == vals.end()) { + cout << "Known values: " << vals.size() << ":"; + FORIT(MAP,vals) { + cout << " " << (*it).first; + } + cout << endl; + bool better = false; + FORIT(vector, ops) { + OP* op = *it; + + if(vals.find(op->o) != vals.end()) { + //cout << " Already computed " << op->o << endl; + continue; // Already done. + } + if(vals.find(op->v1) == vals.end()) { + //cout << " Missing L " << op->v1 << endl; + continue; // Missing input + } + if(vals.find(op->v2) == vals.end()) { + //cout << " Missing R " << op->v2 << endl; + continue; // Missing input + } + + if(op->t == AND) { + vals[op->o] = vals[op->v1] & vals[op->v2]; + } + else if(op->t == OR) { + vals[op->o] = vals[op->v1] | vals[op->v2]; + } + else if(op->t == NOT) { + vals[op->o] = ~vals[op->v1]; + } + else if(op->t == LSHIFT) { + vals[op->o] = vals[op->v1] << op->v3; + } + else if(op->t == RSHIFT) { + vals[op->o] = vals[op->v1] >> op->v3; + } + else if(op->t == SET) { + vals[op->o] = vals[op->v1]; + } + else { + die(); + } + cout << " Computed " << op->o << ": " << vals[op->o] << " from " << op->v1 << " and " << op->v2 << endl; + better = true; + } + if(!better) { + cerr << "No improvements!" << endl; + die(); + } + } + cout << "Answer: " << vals["a"] << endl; +} diff --git a/aoc2015/P08.cpp b/aoc2015/P08.cpp new file mode 100644 index 0000000..1de7871 --- /dev/null +++ b/aoc2015/P08.cpp @@ -0,0 +1,34 @@ +int main() { + LL all = 0, some = 0, p2 = 0; + string s; + while(cin >> s) { + all += s.size(); + int reduced = 2; // End quotes. + for(int i = 0; i < (int)s.size(); i++) { + char c = s[i]; + if(c != '\\') + continue; + reduced++; + i++; + c = s[i]; + if(c == '\\' || c == '"') { + // OK. + } + else { + i+=2; + reduced+=2; + } + } + some += s.size() - reduced; + // Part 2: + for(int i = 0; i < (int)s.size(); i++) { + char c = s[i]; + if(c == '\\' || c == '"') { + p2++; + } + } + p2+=2; + } + cout << "Answer 1: " << (all-some) << endl; + cout << "Answer 2: " << p2 << endl; +} diff --git a/aoc2015/P09.cpp b/aoc2015/P09.cpp new file mode 100644 index 0000000..3bd2d22 --- /dev/null +++ b/aoc2015/P09.cpp @@ -0,0 +1,56 @@ +typedef pair PISS; +#define BIG 9999999 + +map clusters; +set ids; +int D[10][10]; +bool used[10]; + +int bestDist(int from, int left) { + if(left == 0) + return 0; + int best = 0; // BIG for part 1 + FORI((int)ids.size()) { + if(used[i]) + continue; + if(D[from][i] == BIG) { + continue; + } + used[i] = true; + best = max(best, D[from][i] + bestDist(i, left-1)); + used[i] = false; + } + return best; +} + +int main() { + int dist, answer = 0; // BIG for part 1; + FORI(10) { + FORJ(10) { + D[i][j] = BIG; + } + } + string a, s, b; + while(cin >> a >> s >> b >> s >> dist) { + if(ids.find(a) == ids.end()) { + clusters[a] = (int)clusters.size(); + ids.insert(a); + } + if(ids.find(b) == ids.end()) { + clusters[b] = (int)clusters.size(); + ids.insert(b); + } + D[clusters[b]][clusters[a]] = D[clusters[a]][clusters[b]] = dist; + } + + // Try to start for each: + FORJ((int)ids.size()) { + FORI(10) { + used[i] = false; + } + used[j] = true; + answer = max(answer, bestDist(j, (int)ids.size()-1)); + } + + cout << "Answer: " << answer << endl; +} diff --git a/aoc2015/P10.cpp b/aoc2015/P10.cpp new file mode 100644 index 0000000..17dd6ab --- /dev/null +++ b/aoc2015/P10.cpp @@ -0,0 +1,21 @@ +int main() { + GS(s); + cout << "Init: " << s << endl; + FORK(50) { // 40 for part 1 + stringstream ss; + int i = 0; + while(i < (int)s.size()) { + int j = i; + while(j+1 < (int)s.size() && s[j+1]==s[i]) { + j++; + } + ss << ""; + ss << (char)('0'+((j-i)+1)); + ss << s[i]; + //cout << i << " Added " << ((j-i)+1) << " and " << s[i] << endl; + i = j+1; + } + s = ss.str(); + cout << k << ": " << s << " size " << s.size() << endl; + } +} diff --git a/aoc2015/P11.cpp b/aoc2015/P11.cpp new file mode 100644 index 0000000..2e8296f --- /dev/null +++ b/aoc2015/P11.cpp @@ -0,0 +1,61 @@ +void next(string &pw, int idx) { + if(pw[idx] == 'z') { + pw[idx] = 'a'; + next(pw, idx-1); + } + else { + pw[idx]++; + } +} +void next(string &pw) { + next(pw, 7); +} + +bool check(string &pw) { + bool ok = false; + int len = (int)pw.size(); + for(int i = 0; i+2 < len; i++) { + if(pw[i]+2 == pw[i+1]+1 && pw[i+1]+1 == pw[i+2]+0) { + ok = true; + break; + } + } + if(!ok) { + cout << " " << pw << " has not incrementing 3" << endl; + return false; + } + FORI(len) { + char c = pw[i]; + if(c == 'o' || c == 'i' || c == 'l') { + cout << " " << pw << " contains illegal letter" << endl; + pw[i]++; // Quick skip. + return false; + } + } + ok = false; + FORI(len-3) { + if(pw[i] == pw[i+1]) { + for(int j = i+2; j+1 < len; j++) { + if(pw[j] == pw[j+1]) { + ok = true; + break; + } + } + } + if(ok) { + break; + } + } + if(!ok) { + cout << " " << pw << " Missing double pairs" << endl; + } + return ok; +} + +int main() { + GS(pw); + do { + next(pw); + } while(!check(pw)); + cout << pw << endl; +} diff --git a/aoc2015/P13.cpp b/aoc2015/P13.cpp new file mode 100644 index 0000000..119c666 --- /dev/null +++ b/aoc2015/P13.cpp @@ -0,0 +1,80 @@ +// Remove "happiness units by sitting next to " and "would " from input +struct PermutationNode { + PermutationNode *next; + int val; +}; +struct PermutationHandler { + PermutationNode *nodes; + + PermutationHandler(int size) { + nodes = new PermutationNode[size+1]; + for(int i = 0; i < size; ++i) { + nodes[i+1].val = i; + nodes[i].next = &(nodes[i+1]); + } + nodes[size].next = NULL; + } + + ~PermutationHandler() { + delete[] nodes; + } + + PermutationNode* root() { + return &(nodes[0]); + } +}; + +int cost[10][10], perm[10], N = 0, best = -99999; + +void compute(const int n, PermutationHandler &ph) { + if(n == N) { + int sum = 0; + FORI(N) { + int a = perm[i]; + int b = perm[(i+1)%N]; + sum += cost[a][b] + cost[b][a]; + } + best = max(best, sum); + return; + } + // try all combinations: + PermutationNode *node = ph.root(); + while(node->next != NULL) { + PermutationNode *node2 = node->next; + // remove n from permutation: + node->next = node2->next; + perm[n] = node2->val; + compute(n+1, ph); + // re-insert in permutation and go to next: + node->next = node2; // n->next is already set (never changes) + node = node2; + } +} + +int main() { + FORI(10) { + FORJ(10) { + cost[i][j] = 0; + } + } + map m; + + string a, b, op; + int v; + while(cin >> a >> op >> v >> b) { + if(m.find(a) == m.end()) { + m[a] = (int)m.size(); + } + if(m.find(b) == m.end()) { + m[b] = (int)m.size(); + } + cost[m[a]][m[b]] = op == "gain" ? v : -v; + } + N = (int)m.size(); + N++; // Don't do this for part 1 + cout << "N=" << N << endl; + + PermutationHandler ph(N); + compute(0, ph); + cout << "Answer: " << best << endl; +} diff --git a/aoc2015/P14.cpp b/aoc2015/P14.cpp new file mode 100644 index 0000000..d3d51f6 --- /dev/null +++ b/aoc2015/P14.cpp @@ -0,0 +1,40 @@ +// Remove from input: "can fly ", "km/s for ", "seconds, but then must rest for ", and " seconds." +// Insert time in top of input +int main() { + long t1[10], t2[10], speed[10], points[10], pos[10]; + GI(T); + FORI(10) { + points[i] = pos[i] = 0; + } + string s; + // Read reindeers: + int N = 0; + while(cin >> s >> speed[N] >> t1[N] >> t2[N]) { + N++; + } + // Simulate: + FORI(T) { // Each round + long longest = 0; + FORJ(N) { // Update positions: + long cycleLength = t1[j]+t2[j]; + long positionInCycle = i % cycleLength; + if(positionInCycle < t1[j]) { + pos[j] += speed[j]; // Only move when not resting + } + longest = max(longest, pos[j]); + } + // Give points: + FORJ(N) { + if(pos[j] == longest) { + points[j]++; + } + } + } + + long best = 0; + FORJ(N) { + best = max(best, points[j]); + } + + cout << "-------" << endl << "Answer: " << best << endl; +} diff --git a/aoc2015/P15.cpp b/aoc2015/P15.cpp new file mode 100644 index 0000000..c1767f3 --- /dev/null +++ b/aoc2015/P15.cpp @@ -0,0 +1,59 @@ +// Remove "," from input + +int stats[10][5]; +int N = 0, usage[10]; +long best = 0; +int CAP = 100; +string names[10]; + +void go(int ingredient, int pos) { + if(ingredient == N-1) { + usage[N-1] = CAP-pos; + long test = 1; + cout << "Test "; + FORJ(N) { + cout << names[j] << usage[j] << " "; + } + FORI(4) { // Add for stat i (only 4 stats, not calories) + long sum = 0; + FORJ(N) { // Ingredient j + sum += usage[j] * stats[j][i]; + } + //cout << " " << sum << endl; + sum = max(sum, 0L); + test *= sum; + } + cout << "-> " << test << endl; + + // For part 2, compute calories: + long calories = 0; + FORJ(N) { + calories += usage[j] * stats[j][4]; + } + if(calories == 500) { + best = max(best, test); + } + return; + } + for(int i = pos; i <= CAP; i++) { + usage[ingredient] = i-pos; + go(ingredient+1, i); + } +} + +int main() { + // Read input: + string s; + cout << "STATS:" << endl; + while(cin >> names[N]) { + cout << names[N]; + FORI(5) { + cin >> s >> stats[N][i]; + cout << " " << stats[N][i]; + } + cout << endl; + N++; + } + go(0, 0); + cout << "Answer: " << best << endl; +} diff --git a/aoc2015/P16.cpp b/aoc2015/P16.cpp new file mode 100644 index 0000000..ec12ee7 --- /dev/null +++ b/aoc2015/P16.cpp @@ -0,0 +1,60 @@ +// Remove "," and ":" from input and add Sue 501 as stopper at end. +typedef map MAP; + +int main() { + GI(N); + MAP goal; + set zero; + FORI(N) { + GS(key); + GI(val); + if(val == 0) { + zero.insert(key); + } + goal[key] = val; + } + GS(ignore); + GI(one); + + string key; + int val; + MAP cur; + + while(cin >> key >> val) { + if(key == "Sue") { + int sue = val-1; + // Check Sue: + bool ok = true; + FORIT(MAP, cur) { + key = it->first; + val = it->second; + if(key == "cats" || key == "trees") { + if(goal[key] >= val) { + ok = false; + break; + } + // More + } + else if(key == "pomeranians" || key == "goldfish") { + if(goal[key] <= val) { + ok = false; + break; + } + } + else { + if(goal[key] != val) { + ok = false; + break; + } + } + } + if(ok) { + cout << "MATCH! " << sue << endl; + } + cur.clear(); + } + else { + cur[key] = val; + } + } +} diff --git a/aoc2015/P17.cpp b/aoc2015/P17.cpp new file mode 100644 index 0000000..484ced8 --- /dev/null +++ b/aoc2015/P17.cpp @@ -0,0 +1,52 @@ +int capacity[100], answer = 0, N = 0, inUse[100], shortest = 1000; + +void go(int remaining, int idx, int len) { + if(0 == remaining) { + cout << "Combination " << answer << " of length " << len << ":"; + FORI(len) { + cout << " " << inUse[i] << "(" << capacity[inUse[i]] << ")"; + } + cout << endl; + if(len < shortest) { + answer = 0; + shortest = len; + } + if(len == shortest) { + answer++; + } + return; + } + if(idx == N) { + return; // No more cups. + } + /*if(capacity[idx] > remaining) { + return; // Can't fill. Skip. + }*/ + //cout << "Try cup " << idx << " of size " << capacity[idx] << ", remaining: " << remaining << endl; + + // Try next cup: + if(idx+1 <= N) { + if(remaining >= capacity[idx]) { + inUse[len] = idx; + go(remaining-capacity[idx], idx+1, len+1); // Use the cup + } + go(remaining, idx+1, len); // Skip the cup + } +} + +int main() { + GI(CAP); + while(cin >> capacity[N]) { + N++; + } + cout << "Elves have " << CAP << " liters. There are " << N << " cups" << endl; + //sort(capacity, capacity+N); + FORI(N) { + cout << " " << capacity[i]; + } + cout << endl; + + go(CAP, 0, 0); + + cout << "Answer: " << answer << endl; +} diff --git a/aoc2015/P18.cpp b/aoc2015/P18.cpp new file mode 100644 index 0000000..7093aff --- /dev/null +++ b/aoc2015/P18.cpp @@ -0,0 +1,69 @@ +bool G1[102][102], G2[102][102]; + +int main() { + GI(steps); + FORI(102) { + FORJ(102) { + G1[i][j] = G2[i][j] = false; + } + } + string s; + int W, row = 1; + while(cin >> s) { + W = (int)s.size(); + FORI(W) { + G1[row][i+1] = s[i] == '#'; + } + row++; + } + G1[1][1] = G1[1][W] = G1[W][1] = G1[W][W] = true; // Part 2 + + cout << "Initial configuration:" << endl; + FORY(W) { + FORX(W) { + bool b = G1[y+1][x+1]; + cout << (b ? '#' : '.'); + } + cout << endl; + } + cout << endl; + + FORI(steps) { + for(int x = 1; x <= W; x++) { + for(int y = 1; y <= W; y++) { + int neighbours = 0; + for(int xx = x-1; xx <= x+1; xx++) { + for(int yy = y-1; yy <= y+1; yy++) { + if(!(xx==x&&yy==y) && G1[yy][xx]) { + neighbours++; + } + } + } + if(G1[y][x]) { + G2[y][x] = neighbours == 2 || neighbours == 3; + } + else { + G2[y][x] = neighbours == 3; + } + } + } + // Part 2: + G2[1][1] = G2[1][W] = G2[W][1] = G2[W][W] = true; + + int on = 0; + cout << "After " << (i+1) << " steps:" << endl; + FORY(W) { + FORX(W) { + bool b = G2[y+1][x+1]; + if(b) + on++; + cout << (b ? '#' : '.'); + } + cout << endl; + } + swap(G1, G2); + cout << on << " on " << endl; + cout << endl; + + } +} diff --git a/aoc2015/P19.cpp b/aoc2015/P19.cpp new file mode 100644 index 0000000..22fb093 --- /dev/null +++ b/aoc2015/P19.cpp @@ -0,0 +1,110 @@ +// Replace Mg with g, Ca with a, Al with l, Si with S, Th with h, Ti with i, Ar with A, Rn with R. +// Remove lines starting with CR, as it is never used. +// +// Always repace N with HS. TODO. +// Doublers: a -> aa, i -> ii DONE. + +#include + +LL hashCode(string &s) { + LL ret = 0; + FORUI(s.size()) { + ret = 41*ret + s[i]; + } + return ret; +} + +int iteration = 1; + +vector V; +string start = "e"; +int best = 999; +int cnt = 0; +map seen; +map built; + +void reduce(string s, int iterations) { + if(s == start) { + best = min(best, iterations); + return; + } + if(iterations > best) { + return; // Too deep. + } + + // Try a and i replacement: + string::size_type pos; + while((pos = s.find("aaa")) != string::npos) { + s = s.replace(pos, 3, "aa"); + iterations++; + } + while((pos = s.find("iii")) != string::npos) { + s = s.replace(pos, 3, "ii"); + iterations++; + } + + LL hash = hashCode(s); + if(seen.find(hash) == seen.end()) { + seen[hash] = iterations; + } + else { + int old = seen[hash]; + if(old <= iterations) { + return; // Already done better. + } + cout << "Improved path to " << s << " from " << seen[hash] << " to " << iterations << endl; + seen[hash] = iterations; + } + + if(cnt++ % 1000000 == 0) + cout << cnt << " Best: " << best << ", now: " << iterations << " Trying " << s << " of size " << s.size() << endl; + + FORIT(vector, V) { + string from = it->first; + string to = it->second; + //cout << "Trying replacement " << from << " -> " << to << endl; + + pos = -1; + while((pos = s.find(to, pos+1)) != string::npos) { + string s2 = s; + s2 = s2.replace(pos, to.size(), from); + reduce(s2, iterations+1); + pos++; + } + } +} + +bool cmp(const PS &a, const PS &b) { + if(a.second.size() != b.second.size()) + return a.second.size() > b.second.size(); + + if(a.second != b.second) + return a.second < b.second; + return a.first < b.first; +} + +int main() { + GI(N); + FORI(N) { + GS(from); + GS(arrow); + GS(to); + V.push_back(PS(from,to)); + } + GS(target); + cout << N << " lines" << endl; + + sort(V.begin(), V.end(), cmp); + + FORIT(vector, V) { + string from = it->first; + string to = it->second; + cout << " " << from << " -> " << to << endl; + } + + cout << "Target size: " << target.size() << endl; + + reduce(target, 0); + + cout << best << endl; +} diff --git a/aoc2015/run.sh b/aoc2015/run.sh new file mode 100755 index 0000000..fff7fb7 --- /dev/null +++ b/aoc2015/run.sh @@ -0,0 +1,37 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2015/top.cpp b/aoc2015/top.cpp new file mode 100644 index 0000000..41a5f17 --- /dev/null +++ b/aoc2015/top.cpp @@ -0,0 +1,73 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2016/P01.cpp b/aoc2016/P01.cpp new file mode 100644 index 0000000..bdccb30 --- /dev/null +++ b/aoc2016/P01.cpp @@ -0,0 +1,38 @@ +// Input cleanup: Remove "," and add space after each L and R +int main() { + PI p(0,0); + int dir = 0; + string s; + set S; + S.insert(p); + + while(cin >> s) { + if(s[0] == 'L') + dir = (dir+3)%4; + else + dir = (dir+1)%4; + GI(dist); + FORI(dist) { + switch(dir) { + case 0: + p.XX++; + break; + case 1: + p.YY++; + break; + case 2: + p.XX--; + break; + case 3: + p.YY--; + break; + } + if(S.find(p) != S.end()) { + cout << "Answer 2: " << (abs(p.XX)+abs(p.YY)) << endl; + } + else + S.insert(p); + } + } + cout << "Answer 1: " << (abs(p.XX)+abs(p.YY)) << endl; +} diff --git a/aoc2016/P02.cpp b/aoc2016/P02.cpp new file mode 100644 index 0000000..c131f1c --- /dev/null +++ b/aoc2016/P02.cpp @@ -0,0 +1,76 @@ +int main() { + string s; + PI p(-2,0); // Assume middle is 0,0 + + while(cin >> s) { + FORUI(s.size()) { + char c = s[i]; + switch(c) { + case 'U': + p.YY = max(-(2-abs(p.XX)), p.YY-1); + break; + case 'D': + p.YY = min((2-abs(p.XX)), p.YY+1); + break; + case 'L': + p.XX = max(-(2-abs(p.YY)), p.XX-1); + break; + case 'R': + p.XX = min((2-abs(p.YY)), p.XX+1); + break; + default: + die(); + } + } + // Output: + switch(p.YY) { + case -2: + cout << "1"; + break; + case -1: + cout << p.XX+3; + break; + case 0: + cout << p.XX+7; + break; + case 1: + cout << (char)(p.XX + 1 + 'A'); + break; + case 2: + cout << "D"; + break; + default: + die(); + } + } + cout << endl; + + + /* Part 1 below: + PI p(1,1); // 5 + while(cin >> s) { + FORUI(s.size()) { + char c = s[i]; + switch(c) { + case 'U': + p.YY = max(0, p.YY-1); + break; + case 'D': + p.YY = min(2, p.YY+1); + break; + case 'L': + p.XX = max(0, p.XX-1); + break; + case 'R': + p.XX = min(2, p.XX+1); + break; + default: + die(); + } + } + // Output: + cout << (1+3*p.YY) + p.XX; + } + cout << endl; + //*/ +} diff --git a/aoc2016/P03.cpp b/aoc2016/P03.cpp new file mode 100644 index 0000000..78c3db9 --- /dev/null +++ b/aoc2016/P03.cpp @@ -0,0 +1,24 @@ +int main() { + int y[9], answer = 0; + + while(true) { + FORI(9) { + int row = i/3; + int column = i%3; + int idx = 3*column + row; + if(!(cin >> y[idx])) { + cout << answer << endl; + return 0; + } + } + + FORI(3) { + int *x = &(y[3*i]); + cout << "Triangle check " << x[0] << " " << x[1] << " " << x[2] << endl; + sort(x, x+3); + if(x[0]+x[1] > x[2]) { + answer++; + } + } + } +} diff --git a/aoc2016/P04.cpp b/aoc2016/P04.cpp new file mode 100644 index 0000000..bc9555d --- /dev/null +++ b/aoc2016/P04.cpp @@ -0,0 +1,63 @@ +/* +Input cleanup: +Replace [, ] and - with space + */ +int cnt[26]; +int main() { + int answer = 0; + string s; + while(true) { + stringstream ss; + // Reset: + FORI(26) { + cnt[i] = 0; + } + bool any = false; + while(cin >> s) { + any = true; + char c0 = s[0]; + if(c0 >= '0' && c0 <= '9') { + break; + } + FORUI(s.size()) { + cnt[s[i]-'a']++; + } + ss << s << " "; + } + //cout << " String scanned: " << s << endl; + if(!any) { + cout << answer << endl; + return 0; + } + int id = stoi(s); + cin >> s; // Checksum + vector v; + FORI(26) { + if(cnt[i] > 0) + v.push_back(PIC(-cnt[i],(char)('a'+i))); + } + sort(v.begin(), v.end()); + // Check against checksum: + bool ok = v.size() >= s.size(); + if(ok) { + FORUI(s.size()) { + if(s[i] != v[i].second) { + ok = false; + break; + } + } + } + if(ok) { + answer += id; + s = ss.str(); + // Output: + FORUI(s.size()) { + if(s[i] == ' ') + continue; + int x = (s[i]-'a')+id; + s[i] = (char)('a'+x%26); + } + cout << "OK " << s << " with ID " << id << endl; + } + } // while true +} // int main diff --git a/aoc2016/P05.cpp b/aoc2016/P05.cpp new file mode 100644 index 0000000..4331855 --- /dev/null +++ b/aoc2016/P05.cpp @@ -0,0 +1,392 @@ +class MD5 { +public: + typedef uint32_t size_type; // must be 32bit + + MD5(); + MD5(const string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + string hexdigest() const; + friend ostream& operator<<(ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// + +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return (x&y) | (~x&z); +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return (x&z) | (y&~z); +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return string(buf); +} + +////////////////////////////// + +ostream& operator<<(ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} + +////////////////////////////// + +string md5(const string str) { + MD5 md5 = MD5(str); + return md5.hexdigest(); +} + +int main() { + GS(s); + + string answer = "--------"; + int letters = 0; + for(LL i = 0; true; i++) { + string t1 = s + to_string(i); + string t2 = md5(t1); + //cout << " Trying " << t1 << " -> " << t2 << endl; + + bool ok = true; + FORJ(5) { // For part 1, use 5. + if(t2[j] != '0') { + ok = false; + break; + } + } + if(ok) { + char c1 = t2[5]; + char c2 = t2[6]; + if(c1 >= '0' && c1 <= '7' && answer[c1-'0'] == '-') { + answer[c1-'0'] = c2; + cout << answer << endl; + letters++; + if(letters == 8) + return 0; + } + } // if ok + } // FOR LL i + cout << endl; +} diff --git a/aoc2016/P06.cpp b/aoc2016/P06.cpp new file mode 100644 index 0000000..e3712b5 --- /dev/null +++ b/aoc2016/P06.cpp @@ -0,0 +1,27 @@ +int cnt[8][26]; + +int main() { + FORI(8) { + FORJ(26) { + cnt[i][j] = 0; + } + } + string s; + while(cin >> s) { + FORUI(s.size()) { + cnt[i][s[i]-'a']++; + } + } // while cin >> s + FORI(8) { + char best; + int bestCnt = 99999; + FORJ(26) { + if(cnt[i][j] < bestCnt && cnt[i][j] > 0) { + bestCnt = cnt[i][j]; + best = (char)(j+'a'); + } + } + cout << best; + } + cout << endl; +} diff --git a/aoc2016/P07.cpp b/aoc2016/P07.cpp new file mode 100644 index 0000000..7a0f7a1 --- /dev/null +++ b/aoc2016/P07.cpp @@ -0,0 +1,81 @@ +bool abba(char *s) { + FORI(4) { + char c = s[i]; + if(c == ']' || c == '[' || c == 0) { + return false; + } + } + if(s[0] == s[1]) + return false; + return s[0] == s[3] && s[1] == s[2]; +} + +bool aba(char *s, PC &pc) { + FORI(3) { + char c = s[i]; + if(c == ']' || c == '[' || c == 0) { + return false; + } + } + if(s[0] == s[1]) + return false; + if(s[0] != s[2]) + return false; + pc.first = s[0]; + pc.second = s[1]; + return true; +} + +int main() { + int answer1 = 0, answer2 = 0, all = 0; + string s; + while(cin >> s) { + set ABA, BAB; + bool isIn = false; + bool hasOutside = false; + bool hasInside = false; + FORUI(s.size()) { + char c = s[i]; + if(c == ']') { + isIn = false; + } + else if(c == '[') { + isIn = true; + } + else { + if(abba(&s[i])) { + if(isIn) + hasInside = true; + else + hasOutside = true; + } + PC pc; + if(aba(&s[i], pc)) { + if(isIn) { + BAB.insert(pc); + } + else { + ABA.insert(pc); + } + } + } + } + if(hasOutside && !hasInside) { + //cout << "1: " << s << endl; + answer1++; + } + FORIT(set, ABA) { + PC pc = *it; + swap(pc.first, pc.second); + if(BAB.find(pc) != BAB.end()) { + cout << "2: " << pc.second << pc.first << pc.second << " / " << pc.first << pc.second << pc.first << " " << s << endl; + answer2++; + break; + } + } + all++; + } + cout << "Answer 1: " << answer1 << endl; + cout << "Answer 2: " << answer2 << endl; // Less than 232 + cout << "Total lines: " << all << endl; +} diff --git a/aoc2016/P08.cpp b/aoc2016/P08.cpp new file mode 100644 index 0000000..29a1a89 --- /dev/null +++ b/aoc2016/P08.cpp @@ -0,0 +1,64 @@ +/* +Fix input: +'x' -> ' ' +'rotate row y=' -> 'y ' +' by ' -> ' ' +'rotate column =' -> 'x ' + */ +#define W 50 +#define H 6 + +int main() { + bool D[6][50]; + FORY(H) { + FORX(W) { + D[y][x] = false; + } + } + string op; + int a, b; + while(cin >> op >> a >> b) { + if(op == "rect") { + FORY(b) { + FORX(a) { + D[y][x] = true; + } + } + } + else if(op == "x") { + FORI(b) { + bool last = D[H-1][a]; + for(int y = H-1; y > 0; y--) { + D[y][a] = D[y-1][a]; + } + D[0][a] = last; + } + } + else if(op == "y") { + FORI(b) { + bool last = D[a][W-1]; + for(int x = W-1; x > 0; x--) { + D[a][x] = D[a][x-1]; + } + D[a][0] = last; + } + } + else { + die(); + } + int on = 0; + FORY(H) { + FORX(W) { + if(D[y][x]) { + on++; + cout << '#'; + } + else { + cout << '.'; + } + } + cout << endl; + } + cout << on << endl; + } // while cin >> ... +} diff --git a/aoc2016/P09.cpp b/aoc2016/P09.cpp new file mode 100644 index 0000000..309a1ac --- /dev/null +++ b/aoc2016/P09.cpp @@ -0,0 +1,34 @@ +LL count(char *s, int len, LL mult) { + LL answer = 0; + + FORI(len) { + char c = s[i]; + if(c != '(') { + //cout << "NORMAL " << c << endl; + answer+=mult; + continue; + } + // c == '(': Parse ints: + int a = 0, b = 0; + i++; + while((c = s[i]) != 'x') { + a = 10*a + (c-'0'); + i++; + } + // c == 'x' + i++; + while((c = s[i]) != ')') { + b = 10*b + (c-'0'); + i++; + } + // c == ')' + answer += mult * count(&s[i+1], a, b); + i += a; + } + return answer; +} + +int main() { + GS(s); cout << "INPUT " << s << endl; + cout << count(&s[0], (int)s.size(), 1) << endl; +} diff --git a/aoc2016/P10.cpp b/aoc2016/P10.cpp new file mode 100644 index 0000000..3159652 --- /dev/null +++ b/aoc2016/P10.cpp @@ -0,0 +1,93 @@ +struct Bot { + int id, low, high, vals[2],numVals; +}; + +/* + Clean input, rm "gives low to " and "and high to ", "goes to bot " + */ +int main() { + map bots; + vector input; // value x goes to bot y + + string op; + while(cin >> op) { + if(op == "bot") { + Bot *bot = new Bot; + bot->numVals = 0; + + cin >> bot->id; + GS(t1); + GI(a); // low + if(t1 == "output") + a = -a-1; + bot->low = a; + GS(t2); + GI(b); // high + if(t2 == "output") + b = -b-1; + bot->high = b; + + bots[bot->id] = bot; + } + else if(op == "value") { + GI(a); GI(b); + input.push_back(PI(a,b)); + } + else { + die(); // unknown command! + } + } + + stack ready; + map output; + + // Initial values: + FORIT(vector, input) { + int value = (*it).first; + int botId = (*it).second; + Bot *bot = bots[botId]; + bot->vals[bot->numVals++] = value; + if(bot->numVals == 2) { + ready.push(botId); + } + } + + while(!ready.empty()) { + Bot *bot = bots[ready.top()]; + ready.pop(); + sort(bot->vals, bot->vals+2); + + cout << "Bot " << bot->id << " which gives low (" << bot->vals[0] << ") to " << bot->low << " and high (" << bot->vals[1] << ") to " << bot->high << endl; + if(bot->vals[0] == 17 && bot->vals[1] == 61) { + cout << "HANDLES!" << endl; + } + + // Handle low: + if(bot->low < 0) { + int o = -bot->low-1; + output[o] = bot->vals[0]; + cout << "Output " << o << ": " << bot->vals[0] << endl; + } + else { + Bot *b2 = bots[bot->low]; + b2->vals[b2->numVals++] = bot->vals[0]; + if(b2->numVals == 2) { + ready.push(b2->id); + } + } + // Handle high: + if(bot->high < 0) { + int o = -bot->high-1; + output[o] = bot->vals[1]; + cout << "Output " << o << ": " << bot->vals[1] << endl; + } + else { + Bot *b2 = bots[bot->high]; + b2->vals[b2->numVals++] = bot->vals[1]; + if(b2->numVals == 2) { + ready.push(b2->id); + } + } + } + cout << "Answer 2: " << (output[0]*output[1]*output[2]) << endl; +} diff --git a/aoc2016/P11.cpp b/aoc2016/P11.cpp new file mode 100644 index 0000000..180dcfc --- /dev/null +++ b/aoc2016/P11.cpp @@ -0,0 +1,242 @@ +// Clean up input, so it matches the example from the problem statement: +// Line: * with = X[MG], X=0,1,... +#define SIZE 7 + +unsigned int G[SIZE], M[SIZE], elevator = 0, size; // Floors and elevator + +void print() { + FORI(4) { + unsigned int f = 4-i-1; + cout << "F" << (f+1) << " "; + if(elevator == f) + cout << "E "; + else + cout << ". "; + FORJ(size) { + if(G[j] == f) + cout << j << "G "; + else + cout << ". "; + if(M[j] == f) + cout << j << "M "; + else + cout << ". "; + } + cout << endl; + } +} + +void decode(ULL x) { + FORI(size) { + M[size-1-i] = x & 3; + x >>= 2; + } + FORI(size) { + G[size-1-i] = x & 3; + x >>= 2; + } + elevator = x; + // Check if state is valid: + bool ok = false; + FORI(size) { + if(elevator == M[i] || elevator == G[i]) { + ok = true; + break; + } + } + if(!ok) { + print(); + cerr << "Invalid state!" << endl; + die(); + } +} + +ULL encode() { + ULL ret = elevator; + FORI(size) { + ret = (ret << 2) + G[i]; + } + FORI(size) { + ret = (ret << 2) + M[i]; + } + return ret; +} + +bool isValid() { + FORI(size) { + unsigned int m = M[i]; + unsigned int g = G[i]; + if(m != g) { + FORJ(size) { + if(G[j] == m) + return false; // Generator at unshielded m + } + } + } + return true; +} + +bool isDone() { + if(elevator != 3) + return false; + FORI(size) { + if(M[i] != 3) + return false; + if(G[i] != 3) + return false; + } + return true; +} + +int main() { + // Read input file (modified): + cin >> size; + FORJ(3) { + GI(Q); + FORI(Q) { + GS(s); + unsigned int id = s[0]-'0'; + if(s[1] == 'G') { + G[id] = j; + cout << "Generator " << id << " on floor " << j << endl; + } + else { + M[id] = j; + cout << "Microchip " << id << " on floor " << j << endl; + } + } + } + + // Simulate all possibilities: + set s1, s2, seen; + ULL state = encode(); + s1.insert(state); + seen.insert(state); + cout << "Initial encoded state: " << state << endl; + + for(unsigned int iteration = 0; !s1.empty(); iteration++) { + cout << "Handling iteration " << iteration << ", states: " << s1.size() << endl; + FORIT(set, s1) { + state = *it; + decode(state); + + //cout << "Iteration " << iteration << " state:" << endl; + //print(); + + if(isDone()) { + cout << "Answer: " << iteration << endl; + return 0; + } + + // Try all movements and place in s2: + vector stuff; + FORI(size) { + if(M[i] == elevator) { + stuff.push_back(PCI('M',i)); + } + if(G[i] == elevator) { + stuff.push_back(PCI('G',i)); + } + } + // Try to move one thing: + ULL oldState = encode(); + FORUI(stuff.size()) { + bool isM = stuff[i].first == 'M'; + int id = stuff[i].second; + if(elevator > 0) { // Elevator down: + elevator--; + if(isM) { + M[id]--; + } + else { + G[id]--; + } + if(isValid()) { + ULL x = encode(); + if(seen.find(x) == seen.end()) { + seen.insert(x); + s2.insert(x); + } + } + decode(oldState); + } + if(elevator < 3) { // Elevator Up: + elevator++; + if(isM) { + M[id]++; + } + else { + G[id]++; + } + if(isValid()) { + ULL x = encode(); + if(seen.find(x) == seen.end()) { + seen.insert(x); + s2.insert(x); + } + } + decode(oldState); + } + } + // Try to move two things: + FORI((int)stuff.size()-1) { + for(int j = i+1; j < (int)stuff.size(); j++) { + bool isMI = stuff[i].first == 'M'; + int idI = stuff[i].second; + bool isMJ = stuff[j].first == 'M'; + int idJ = stuff[j].second; + if(elevator > 0) { // Elevator down: + elevator--; + if(isMI) { + M[idI]--; + } + else { + G[idI]--; + } + if(isMJ) { + M[idJ]--; + } + else { + G[idJ]--; + } + if(isValid()) { + ULL x = encode(); + if(seen.find(x) == seen.end()) { + seen.insert(x); + s2.insert(x); + } + } + decode(oldState); + } + if(elevator < 3) { // Elevator Up: + elevator++; + if(isMI) { + M[idI]++; + } + else { + G[idI]++; + } + if(isMJ) { + M[idJ]++; + } + else { + G[idJ]++; + } + if(isValid()) { + ULL x = encode(); + if(seen.find(x) == seen.end()) { + seen.insert(x); + s2.insert(x); + } + } + decode(oldState); + } // if elevator + } // for j + } // FORI + } // FORIT(s1) + + swap(s1, s2); + s2.clear(); + } + cout << "Impossible!" << endl; +} diff --git a/aoc2016/P12.cpp b/aoc2016/P12.cpp new file mode 100644 index 0000000..39ad772 --- /dev/null +++ b/aoc2016/P12.cpp @@ -0,0 +1,76 @@ +LL registers[4] = {0,0,1,0}; // a-d. Use 0 for c in part 1 + +struct OP { + string op, x, y; +}; + +int main() { + OP op; + vector ops; + + while(cin >> op.op) { + if(op.op == "cpy") { + cin >> op.x >> op.y; + } + else if(op.op == "inc") { + cin >> op.x; + } + else if(op.op == "dec") { + cin >> op.x; + } + else if(op.op == "jnz") { + cin >> op.x >> op.y; + } + else { + die(); + } + ops.push_back(op); + } + + int idx = 0; + while(idx < (int)ops.size()) { + OP op = ops[idx]; + //cout << "Line " << idx << " "; + if(op.op == "cpy") { + int val; + if(op.x[0] >= 'a' && op.x[0] <= 'd') { + val = registers[op.x[0]-'a']; + } + else { + val = stoi(op.x); + } + registers[op.y[0]-'a'] = val; + //cout << "COPY " << op.x << " into " << op.y << endl; + idx++; + } + else if(op.op == "inc") { + registers[op.x[0]-'a']++; + //cout << "INC " << op.x << endl; + idx++; + } + else if(op.op == "dec") { + registers[op.x[0]-'a']--; + //cout << "DEC " << op.x << endl; + idx++; + } + else if(op.op == "jnz") { + int inc; + if(op.x[0] >= 'a' && op.x[0] <= 'd') { + inc = registers[op.x[0]-'a']; + } + else { + inc = stoi(op.x); + } + if(inc == 0) + idx++; + else + idx += stoi(op.y); + //cout << "JUMP " << op.x << " dist " << op.y << " test " << inc << endl; + } + FORK(4) { + //cout << " " << registers[k]; + } + //cout << endl; + } + cout << "Answer: " << registers[0] << endl; // not 1, 42 +} diff --git a/aoc2016/P13.cpp b/aoc2016/P13.cpp new file mode 100644 index 0000000..f4fd5c1 --- /dev/null +++ b/aoc2016/P13.cpp @@ -0,0 +1,55 @@ +int fav; + +bool isFree(PI &p) { + LL x = p.first; + LL y = p.second; + if(x < 0 || y < 0) + return false; // out of bounds + LL test = x*x + 3*x + 2*x*y + y + y*y + fav; + int ones = 0; + while(test > 0) { + if(test & 1) { + ones++; + } + test >>= 1; + } + //cout << x << ", " << y << " Ones: " << ones << endl; + return ones % 2 == 0; +} + +int main() { + cin >> fav; + set seen, s1, s2; + PI p(1,1); + seen.insert(p); + s1.insert(p); + + for(int iteration = 0; iteration < 50; iteration++) { + cout << "Iteration " << iteration << ": " << s1.size() << endl; + FORIT(set, s1) { + p = *it; + int x = p.XX, y = p.YY; + /*if(x == 31 && y == 39) { // Part 1 + cout << "Answer: " << iteration << endl; + return 0; + }*/ + + for(int xx = x-1; xx <= x+1; xx++) { + for(int yy = y-1; yy <= y+1; yy++) { + if(xx == x || yy == y) { // Ugly, but works. No diagonal moving. + PI p2(xx,yy); + if(isFree(p2) && seen.find(p2) == seen.end()) { + //cout << "Free: " << p2.XX << " " << p2.YY << endl; + s2.insert(p2); + seen.insert(p2); + } // if seen.find(p2) + } // if not diagonal + } // for yy + } // for xx + } // FORIT + + swap(s1,s2); + s2.clear(); + } + cout << "Seen: " << seen.size() << endl; +} diff --git a/aoc2016/P14.cpp b/aoc2016/P14.cpp new file mode 100644 index 0000000..41cc269 --- /dev/null +++ b/aoc2016/P14.cpp @@ -0,0 +1,414 @@ +class MD5 { +public: + typedef uint32_t size_type; // must be 32bit + + MD5(); + MD5(const string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + string hexdigest() const; + friend ostream& operator<<(ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// + +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return (x&y) | (~x&z); +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return (x&z) | (y&~z); +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return string(buf); +} + +////////////////////////////// + +ostream& operator<<(ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} + +////////////////////////////// + +string md5(const string str) { + MD5 md5 = MD5(str); + return md5.hexdigest(); +} + + + +int main() { + GS(salt); + + vector v; + int found = 0; + for(long i = 1; found < 90; i++) { + string t = salt + to_string(i); + FORK(2017) // Just 1 for part 1 + t = md5(t); + //cout << " Trying " << t1 << " -> " << t2 << endl; + + bool ok = false; + char c; + for(int j = 4; j < 32; j++) { + if(t[j] == t[j-1] && t[j] == t[j-2] && t[j] == t[j-3] && t[j] == t[j-4]) { + ok = true; + c = t[j]; + break; + } + } + if(ok) { + for(long k = max((long)0, i-1000); k < i; k++) { + string q = salt + to_string(k); + FORJ(2017) // Just 1 for part 1 + q = md5(q); + for(int j = 2; j < 32; j++) { + if(q[j] == q[j-1] && q[j-2] == q[j]) { + if(q[j] == c) { + found++; + v.push_back(PLL(k,i)); + cout << found << " " << k << " " << i << endl; + } + break; // So we don't count match more than once. + } + } // for j + } // for k + } // if ok + } // FOR long i + + sort(v.begin(),v.end()); + int cnt = 1; + LL prev = -1; + FORIT(vector,v) { + LL a = it->first; + if(a == prev) + continue; // Same. + prev = a; + LL b = it->second; + cout << "Match " << cnt++ << ": " << a << " -> " << b << endl; + } +} diff --git a/aoc2016/P15.cpp b/aoc2016/P15.cpp new file mode 100644 index 0000000..727eef9 --- /dev/null +++ b/aoc2016/P15.cpp @@ -0,0 +1,22 @@ +// Clean input by rm "Disc #", "positions; at time=0, it is at position ", ".", "har " +int size[10], startPosition[10]; + +int main() { + int SIZE; + while(cin >> SIZE >> size[SIZE-1] >> startPosition[SIZE-1]) { + // Read input :) + } + for(long time0 = 0; true; time0++) { + bool ok = true; + FORI(SIZE) { + if((startPosition[i] + time0 + i+1) % size[i] != 0) { + ok = false; + break; + } + } + if(ok) { + cout << time0 << endl; + return 0; + } + } // for time0 +} diff --git a/aoc2016/P16.cpp b/aoc2016/P16.cpp new file mode 100644 index 0000000..76afbbe --- /dev/null +++ b/aoc2016/P16.cpp @@ -0,0 +1,60 @@ +#define EVEN(a) (((a) & 1) == 0) +#define ODD(a) (((a) & 1) == 1) + +bitset<100000000> a, b; +int size; + +// primes.set(); +// primes.set(notAPrimeI, false); + +void expand() { + FORI(size) { + b[size-1-i] = a[i]; + } + b.flip(); + a[size] = 0; + FORI(size) { + a[size+i+1] = b[i]; + } + size = 2*size+1; +} + +void checksumReduce() { + for(int i = 0; i < size; i+=2) { + a[i/2] = a[i] == a[i+1]; + } + size /= 2; +} + +void print() { + cout << size << " "; + FORI(size) { + cout << a[i]; + } + cout << endl; +} + +int main() { + // Init a: + GS(s); GI(disk); + size = (int)s.size(); + FORI(size) { + a.set(i, s[i] == '1'); + } + cout << "Input" << endl; + print(); + + cout << "Expanding" << endl; + while(size < disk) { + expand(); + //print(); + } + + size = disk; + + cout << "Computing checksum" << endl; + while(size % 2 == 0) { + checksumReduce(); + } + print(); +} diff --git a/aoc2016/P17.cpp b/aoc2016/P17.cpp new file mode 100644 index 0000000..73ccbb7 --- /dev/null +++ b/aoc2016/P17.cpp @@ -0,0 +1,407 @@ +class MD5 { +public: + typedef uint32_t size_type; // must be 32bit + + MD5(); + MD5(const string& text); + void update(const unsigned char *buf, size_type length); + void update(const char *buf, size_type length); + MD5& finalize(); + string hexdigest() const; + friend ostream& operator<<(ostream&, MD5 md5); + +private: + void init(); + typedef unsigned char uint1; // 8bit + typedef unsigned int uint4; // 32bit + enum {blocksize = 64}; // VC6 won't eat a const static int here + + void transform(const uint1 block[blocksize]); + static void decode(uint4 output[], const uint1 input[], size_type len); + static void encode(uint1 output[], const uint4 input[], size_type len); + + bool finalized; + uint1 buffer[blocksize]; // bytes that didn't fit in last 64 byte chunk + uint4 count[2]; // 64bit counter for number of bits (lo, hi) + uint4 state[4]; // digest so far + uint1 digest[16]; // the result + + // low level logic operations + static inline uint4 F(uint4 x, uint4 y, uint4 z); + static inline uint4 G(uint4 x, uint4 y, uint4 z); + static inline uint4 H(uint4 x, uint4 y, uint4 z); + static inline uint4 I(uint4 x, uint4 y, uint4 z); + static inline uint4 rotate_left(uint4 x, int n); + static inline void FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); + static inline void II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac); +}; + +#define S11 7 +#define S12 12 +#define S13 17 +#define S14 22 +#define S21 5 +#define S22 9 +#define S23 14 +#define S24 20 +#define S31 4 +#define S32 11 +#define S33 16 +#define S34 23 +#define S41 6 +#define S42 10 +#define S43 15 +#define S44 21 + +/////////////////////////////////////////////// + +// F, G, H and I are basic MD5 functions. +inline MD5::uint4 MD5::F(uint4 x, uint4 y, uint4 z) { + return (x&y) | (~x&z); +} + +inline MD5::uint4 MD5::G(uint4 x, uint4 y, uint4 z) { + return (x&z) | (y&~z); +} + +inline MD5::uint4 MD5::H(uint4 x, uint4 y, uint4 z) { + return x^y^z; +} + +inline MD5::uint4 MD5::I(uint4 x, uint4 y, uint4 z) { + return y ^ (x | ~z); +} + +// rotate_left rotates x left n bits. +inline MD5::uint4 MD5::rotate_left(uint4 x, int n) { + return (x << n) | (x >> (32-n)); +} + +// FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. +// Rotation is separate from addition to prevent recomputation. +inline void MD5::FF(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a+ F(b,c,d) + x + ac, s) + b; +} + +inline void MD5::GG(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + G(b,c,d) + x + ac, s) + b; +} + +inline void MD5::HH(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + H(b,c,d) + x + ac, s) + b; +} + +inline void MD5::II(uint4 &a, uint4 b, uint4 c, uint4 d, uint4 x, uint4 s, uint4 ac) { + a = rotate_left(a + I(b,c,d) + x + ac, s) + b; +} + +////////////////////////////////////////////// + +// default ctor, just initailize +MD5::MD5() +{ + init(); +} + +////////////////////////////////////////////// + +// nifty shortcut ctor, compute MD5 for string and finalize it right away +MD5::MD5(const string &text) +{ + init(); + update(text.c_str(), text.length()); + finalize(); +} + +////////////////////////////// + +void MD5::init() +{ + finalized=false; + + count[0] = 0; + count[1] = 0; + + // load magic initialization constants. + state[0] = 0x67452301; + state[1] = 0xefcdab89; + state[2] = 0x98badcfe; + state[3] = 0x10325476; +} + +////////////////////////////// + +// decodes input (unsigned char) into output (uint4). Assumes len is a multiple of 4. +void MD5::decode(uint4 output[], const uint1 input[], size_type len) +{ + for (unsigned int i = 0, j = 0; j < len; i++, j += 4) + output[i] = ((uint4)input[j]) | (((uint4)input[j+1]) << 8) | + (((uint4)input[j+2]) << 16) | (((uint4)input[j+3]) << 24); +} + +////////////////////////////// + +// encodes input (uint4) into output (unsigned char). Assumes len is +// a multiple of 4. +void MD5::encode(uint1 output[], const uint4 input[], size_type len) +{ + for (size_type i = 0, j = 0; j < len; i++, j += 4) { + output[j] = input[i] & 0xff; + output[j+1] = (input[i] >> 8) & 0xff; + output[j+2] = (input[i] >> 16) & 0xff; + output[j+3] = (input[i] >> 24) & 0xff; + } +} + +////////////////////////////// + +// apply MD5 algo on a block +void MD5::transform(const uint1 block[blocksize]) +{ + uint4 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + decode (x, block, blocksize); + + /* Round 1 */ + FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */ + FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */ + FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */ + FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */ + FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */ + FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */ + FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */ + FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */ + FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */ + FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */ + FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */ + FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */ + FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */ + FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */ + FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */ + FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */ + + /* Round 2 */ + GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */ + GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */ + GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */ + GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */ + GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */ + GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */ + GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */ + GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */ + GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */ + GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */ + GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */ + GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */ + GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */ + GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */ + GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */ + GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */ + + /* Round 3 */ + HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */ + HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */ + HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */ + HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */ + HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */ + HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */ + HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */ + HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */ + HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */ + HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */ + HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */ + HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */ + HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */ + HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */ + HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */ + HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */ + + /* Round 4 */ + II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */ + II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */ + II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */ + II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */ + II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */ + II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */ + II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */ + II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */ + II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */ + II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */ + II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */ + II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */ + II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */ + II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */ + II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */ + II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */ + + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + + // Zeroize sensitive information. + memset(x, 0, sizeof x); +} + +////////////////////////////// + +// MD5 block update operation. Continues an MD5 message-digest +// operation, processing another message block +void MD5::update(const unsigned char input[], size_type length) +{ + // compute number of bytes mod 64 + size_type index = count[0] / 8 % blocksize; + + // Update number of bits + if ((count[0] += (length << 3)) < (length << 3)) + count[1]++; + count[1] += (length >> 29); + + // number of bytes we need to fill in buffer + size_type firstpart = 64 - index; + + size_type i; + + // transform as many times as possible. + if (length >= firstpart) + { + // fill buffer first, transform + memcpy(&buffer[index], input, firstpart); + transform(buffer); + + // transform chunks of blocksize (64 bytes) + for (i = firstpart; i + blocksize <= length; i += blocksize) + transform(&input[i]); + + index = 0; + } + else + i = 0; + + // buffer remaining input + memcpy(&buffer[index], &input[i], length-i); +} + +////////////////////////////// + +// for convenience provide a verson with signed char +void MD5::update(const char input[], size_type length) +{ + update((const unsigned char*)input, length); +} + +////////////////////////////// + +// MD5 finalization. Ends an MD5 message-digest operation, writing the +// the message digest and zeroizing the context. +MD5& MD5::finalize() +{ + static unsigned char padding[64] = { + 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }; + + if (!finalized) { + // Save number of bits + unsigned char bits[8]; + encode(bits, count, 8); + + // pad out to 56 mod 64. + size_type index = count[0] / 8 % 64; + size_type padLen = (index < 56) ? (56 - index) : (120 - index); + update(padding, padLen); + + // Append length (before padding) + update(bits, 8); + + // Store state in digest + encode(digest, state, 16); + + // Zeroize sensitive information. + memset(buffer, 0, sizeof buffer); + memset(count, 0, sizeof count); + + finalized=true; + } + + return *this; +} + +////////////////////////////// + +// return hex representation of digest as string +string MD5::hexdigest() const +{ + if (!finalized) + return ""; + + char buf[33]; + for (int i=0; i<16; i++) + sprintf(buf+i*2, "%02x", digest[i]); + buf[32]=0; + + return string(buf); +} + +////////////////////////////// + +ostream& operator<<(ostream& out, MD5 md5) +{ + return out << md5.hexdigest(); +} + +////////////////////////////// + +string md5(const string str) { + MD5 md5 = MD5(str); + return md5.hexdigest(); +} + +bool isOpen(char c) { + return c >= 'b' && c <= 'f'; +} + +typedef pair PIIS; + +int main() { + GS(s); + + vector v; + v.push_back(PIIS(PI(0,0),"")); + while(!v.empty()) { + // Walk all: + vector v2; + FORIT(vector, v) { + PIIS piis = *it; + PI p = piis.first; + int x = p.XX, y = p.YY; + string path = piis.second; + if(x == 3 && y == 3) { + cout << "path" << " of length " << path.size() << endl; + continue; // Don't continue this path! + } + + string hash = md5(s + path); + // Up: + if(y > 0 && isOpen(hash[0])) { + v2.push_back(PIIS(PI(x,y-1),path+"U")); + } + // Down: + if(y < 3 && isOpen(hash[1])) { + v2.push_back(PIIS(PI(x,y+1),path+"D")); + } + // Left: + if(x > 0 && isOpen(hash[2])) { + v2.push_back(PIIS(PI(x-1,y),path+"L")); + } + // Right: + if(x < 3 && isOpen(hash[3])) { + v2.push_back(PIIS(PI(x+1,y),path+"R")); + } + } // FORIT v + swap(v, v2); + } // while true + cout << "Done" << endl; +} diff --git a/aoc2016/P18.cpp b/aoc2016/P18.cpp new file mode 100644 index 0000000..d04247e --- /dev/null +++ b/aoc2016/P18.cpp @@ -0,0 +1,36 @@ +int main() { + GS(row); + string row2 = row; + long safe = 0; + FORUI(row.size()) { + if(row[i] == '.') { + safe++; + } + } + cout << row << endl; + + bool traps[3]; + GI(ROWS); + FORJ(ROWS-1) { + FORI((int)row.size()) { + traps[0] = (i-1 >= 0) && row[i-1] == '^'; + traps[1] = row[i] == '^'; + traps[2] = (i+1 < row.size()) && row[i+1] == '^'; + + if(( traps[0] && traps[1] && !traps[2]) || + (!traps[0] && traps[1] && traps[2]) || + ( traps[0] && !traps[1] && !traps[2]) || + (!traps[0] && !traps[1] && traps[2])) { + row2[i] = '^'; + } + else { + row2[i] = '.'; + safe++; + } + } // FORI row.size() + swap(row,row2); + cout << row << endl; + } // FORJ 39 + + cout << safe << endl; +} diff --git a/aoc2016/P19.cpp b/aoc2016/P19.cpp new file mode 100644 index 0000000..e0e928f --- /dev/null +++ b/aoc2016/P19.cpp @@ -0,0 +1,46 @@ +// Part 1: +/* +int main() { + GI(size); + int *v = new int[size]; // value is the next in circle. + FORI(size) { + v[i] = (i+1)%size; + } + int p = 0; + while(v[p] != p) { + v[p] = v[v[p]]; // skip + p = v[p]; + } + cout << (p+1) << endl; +}*/ +// Part 2: +int main() { + GI(size); + int *v = new int[size]; + FORI(size) { + v[i] = (i+1); + } + int p = 0; + while(size > 1) { + if(size%10000 == 0) + cout << size << endl; + else if(size%1000 == 0) + cout << "." << endl; + int toRemove = (p+size/2) % size; + if(toRemove == p) { + cerr << "ERROR" << endl; die(); + } + //cout << v[p] << " (" << p << ") steals from " << v[toRemove] << " ("<< toRemove << ") size " << size << " -> " << (size-1) << endl; + for(int i = toRemove; i+1 < size; i++) { + v[i] = v[i+1]; + } + size--; + if(p == size) { + p = 0; + } + else if(toRemove > p) { + p = (p+1)%size; + } + } + cout << v[0] << endl; +} diff --git a/aoc2016/P20.cpp b/aoc2016/P20.cpp new file mode 100644 index 0000000..2b38631 --- /dev/null +++ b/aoc2016/P20.cpp @@ -0,0 +1,91 @@ +// Clean up input by replacing - with space + +// Merge a and b into c +void merge(const vector &a, const vector &b, vector &c) { + vector::const_iterator ita = a.begin(), itb = b.begin(); + LL last = -1; + while(!(ita == a.end() && itb == b.end())) { + if(ita == a.end()) { + PLL p(max(last+1,itb->first),itb->second); + if(p.first <= p.second) { + c.push_back(p); + last = p.second; + } + itb++; + } + else if(itb == b.end()) { + PLL p(max(last+1,ita->first),ita->second); + if(p.first <= p.second) { + c.push_back(p); + last = p.second; + } + ita++; + } + else if(ita->second < itb->first) { + PLL p(max(last+1,ita->first),ita->second); + if(p.first <= p.second) { + c.push_back(p); + last = p.second; + } + ita++; + } + else if(itb->second < ita->first) { + PLL p(max(last+1,itb->first),itb->second); + if(p.first <= p.second) { + c.push_back(p); + last = p.second; + } + itb++; + } + else { // Merge + LL low = min(ita->first, itb->first); + LL high = max(ita->second, itb->second); + low = max(low, last+1); + if(low <= high) { + c.push_back(PLL(low,high)); + last = high; + } + ita++; + itb++; + } + } +} + +void clean(vector &a, vector &b) { + LL last = -1; + FORIT(vector, a) { + if(last == -1) { + b.push_back(*it); + last = it->second; + } + else if(last == it->first-1) { + last = b[b.size()-1].second = it->second; + } + else if(last < it->first-1) { + b.push_back(*it); + last = it->second; + } + } +} + +int main() { + vector b0, b1, b2; + + LL low, high; + while(cin >> low >> high) { + b0.push_back(PLL(low,high)); + merge(b0, b1, b2); + b0.clear(); + b1.clear(); + clean(b2,b1); + b2.clear(); + } // while read + + cout << "Answer 1: " << (b1[0].second+1) << endl; + LL answer2 = 0; + for(int i = 0; i+1 < (int)b1.size(); i++) { + answer2 += (b1[i+1].first - b1[i].second) -1; + } + answer2 += 4294967295L - b1[b1.size()-1].second; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2016/P21.cpp b/aoc2016/P21.cpp new file mode 100644 index 0000000..54ac6ec --- /dev/null +++ b/aoc2016/P21.cpp @@ -0,0 +1,116 @@ +// Cleanup input: RM "with position ", "with letter ", "to position ", "on position of letter " +// Add starting string to top of input. +// For part 2 use "reverse-region" to reverse lines of input file in emacs. +int main() { + GS(s); + int reverseRotations[10]; + FORI((int)s.size()) { + reverseRotations[i] = -1; + } + FORI((int)s.size()) { // i is where letter is found. + int moves = i; + if(i >= 4) { + moves++; + } + moves++; + moves = moves % s.size(); + + int endPosition = (i+moves)%s.size(); + // i is start position + // move is i -> endPosition, so reverse move is: + reverseRotations[endPosition] = (-(endPosition-i)+s.size())%s.size(); + } + + string op, op2; + char c, d; + int a, b, ops=0; + while(cin >> op) { + cout << "Operation " << ops++ << ": " << op << endl; + if(op == "swap") { + cin >> op2; + if(op2 == "position") { + cin >> a >> b; + swap(s[a],s[b]); + } + else if(op2 == "letter") { + cin >> c >> d; + FORUI(s.size()) { + if(s[i] == c) + s[i] = d; + else if(s[i] == d) + s[i] = c; + } + } + } + else if(op == "move") { + //cin >> op2 >> a >> b; // Part 1 + cin >> op2 >> b >> a; // Part 2 + c = s[a]; + // Remove c: + for(int i = a; i+1 < (int)s.size(); i++) { + s[i] = s[i+1]; + } + // Insert c: + for(int i = (int)s.size()-1; i-1 >= b; i--) { + s[i] = s[i-1]; + } + s[b] = c; + } + else if(op == "rotate") { + cin >> op2; + if(op2 == "right") { + cin >> a >> op2; + a = s.size()-a; // Part 2 only + } + else if(op2 == "left") { + cin >> a >> op2; + //a = s.size()-a; // Part 1 only + } + else if(op2 == "based") { + cin >> c; + a = -1; + FORUI(s.size()) { + if(s[i] == c) { + if(a != -1) { + cerr << "Multiple instances of " << c << endl; + die(); + } + a = (int)i; + } + } + + a = reverseRotations[a]; // Part 2 + + /* Part 1: + if(a>=4) + a++; + a++; + a = a%s.size();//*/ + } + + FORI(a) { + c = s[s.size()-1]; + for(int j = (int)s.size()-1; j > 0; j--) { + s[j] = s[j-1]; + } + s[0] = c; + } + + } + else if(op == "reverse") { + cin >> op2 >> a >> op2 >> b; + while(a < b) { + swap(s[a],s[b]); + a++; + b--; + } + } + else { + cerr << "Unknown operation " << op << endl; + die(); + } + cout << "-> " << s << endl; + } + + cout << s << endl; +} diff --git a/aoc2016/P22.cpp b/aoc2016/P22.cpp new file mode 100644 index 0000000..c0ea917 --- /dev/null +++ b/aoc2016/P22.cpp @@ -0,0 +1,33 @@ +// Clean up input by removing first two lines and "/dev/grid/node-x", and "T", and replace "-y" with space. +int main() { + PI data[32][32]; + string ignore; + int x, y, size, used, sizeX = 0, sizeY = 0; + while(cin >> x >> y >> size >> used >> ignore >> ignore) { + data[y][x] = PI(size,used); + sizeX = max(x+1, sizeX); + sizeY = max(y+1, sizeY); + } + cout << "Read grid: " << sizeX << " x " << sizeY << endl; + + long answer = 0; + FORX(sizeX) { + FORY(sizeY) { + PI &a = data[y][x]; + if(a.second == 0) { // No used of a + continue; + } + FORI(sizeX) { + FORJ(sizeY) { + if(!(x==i&&y==j)) { // Not the same + PI &b = data[j][i]; + if(a.second <= (b.first-b.second)) { + answer++; + } + } + } // FORJ + } // FORI + } // FORY + } // FORX + cout << answer << endl; // 814 too low +} diff --git a/aoc2016/run.sh b/aoc2016/run.sh new file mode 100755 index 0000000..fff7fb7 --- /dev/null +++ b/aoc2016/run.sh @@ -0,0 +1,37 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2016/top.cpp b/aoc2016/top.cpp new file mode 100644 index 0000000..41a5f17 --- /dev/null +++ b/aoc2016/top.cpp @@ -0,0 +1,73 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2017/P01.cpp b/aoc2017/P01.cpp new file mode 100644 index 0000000..5f71e76 --- /dev/null +++ b/aoc2017/P01.cpp @@ -0,0 +1,10 @@ +int main() { + GS(s); + long answer = 0; + FORI((int)s.size()) { + if(s[i] == s[(i+s.size()/2)%s.size()]) { // +1 for part 1 + answer += s[i]-'0'; + } + } + cout << answer << endl; +} diff --git a/aoc2017/P02.cpp b/aoc2017/P02.cpp new file mode 100644 index 0000000..aedf72a --- /dev/null +++ b/aoc2017/P02.cpp @@ -0,0 +1,31 @@ +int main() { + string s; + LL answer1 = 0, answer2 = 0; + while(getline(cin, s)) { + stringstream ss; ss << s; + LL x, mi = 9999999999, ma = -99999999; + vector v; + while(ss >> x) { + ma = max(ma, x); + mi = min(mi, x); + v.push_back(x); + } + int added = 0; + FORUI(v.size()) { + FORUJ(v.size()) { + if(i != j) { + if(v[i] % v[j] == 0) { + answer2 += v[i]/v[j]; + added++; + } + } + } + } + if(added != 1) { + cerr << "ERROR: " << added << " on a line!" << endl; + } + answer1 += ma-mi; + } + cout << answer1 << endl; + cout << answer2 << endl; +} diff --git a/aoc2017/P03.cpp b/aoc2017/P03.cpp new file mode 100644 index 0000000..bc0d32f --- /dev/null +++ b/aoc2017/P03.cpp @@ -0,0 +1,53 @@ +int G[1000][1000]; + +int main() { + FORI(1000) { + FORJ(1000) { + G[i][j] = 0; + } + } + G[500][500] = 1; + GI(q); + + PI p(500,500); + int id = 1; + int len = 1, walked = 0; + int dir = 0; + while(id != q) { + switch(dir%4) { + case 0: + p.XX++; + break; + case 1: + p.YY--; + break; + case 2: + p.XX--; + break; + case 3: + p.YY++; + break; + } + walked++; + id++; + int sum = 0; + for(int y = p.YY -1; y <= p.YY+1; y++) { + for(int x = p.XX-1; x <= p.XX+1; x++) { + sum += G[y][x]; + } + } + G[p.YY][p.XX] = sum; + if(sum > q) { + cout << "Answer 2: " << sum << endl; + return 0; // Part 2. + } + //cout << id << ": " << p.XX << " " << p.YY << endl; + if(len == walked) { + walked = 0; + dir++; + if(dir % 2 == 0) + len++; + } + } + cout << "Answer 1: " << (abs(p.XX-500)+abs(p.YY-500)) << endl; +} diff --git a/aoc2017/P04.cpp b/aoc2017/P04.cpp new file mode 100644 index 0000000..8ec60e9 --- /dev/null +++ b/aoc2017/P04.cpp @@ -0,0 +1,20 @@ +int main() { + string s; + int answer = 0; + while(getline(cin, s)) { + stringstream ss; ss << s; + set S; + bool ok = true; + while(ss >> s) { + sort(&s[0], &s[0]+s.size()); // Only for part 2 + if(S.find(s) != S.end()) { + ok = false; + break; + } + S.insert(s); + } // while ss >> s + if(ok) + answer++; + } // while getline + cout << answer << endl; +} diff --git a/aoc2017/P05.cpp b/aoc2017/P05.cpp new file mode 100644 index 0000000..7ebcc97 --- /dev/null +++ b/aoc2017/P05.cpp @@ -0,0 +1,18 @@ +int main() { + LL v[2000]; + int size = 0; + while(cin >> v[size]) { + size++; + } + int idx = 0, steps = 0; + while(idx >= 0 && idx < size) { + int next = idx + v[idx]; + if(v[idx] >= 3) + v[idx]--; // Only part 2 + else + v[idx]++; + idx = next; + steps++; + } + cout << steps << endl; +} diff --git a/aoc2017/P06.cpp b/aoc2017/P06.cpp new file mode 100644 index 0000000..41258e5 --- /dev/null +++ b/aoc2017/P06.cpp @@ -0,0 +1,41 @@ +// Add size to start of input. +int *v, size; + +LL hashCode() { + LL ret = 0; + FORI(size) { + ret = 19*ret + v[i]; + } + return ret; +} + +int main() { + cin >> size; + v = new int[size]; + FORI(size) { + cin >> v[i]; + } + map seen; + int answer = 0; + LL h; + while(seen.find(h = hashCode()) == seen.end()) { + seen[h] = answer; + // Run round: + int best = 0; + for(int i = 1; i < size; i++) { + if(v[i] > v[best]) + best = i; + } + int rem = v[best]; + v[best] = 0; + for(int i = best+1; rem > 0; i++,rem--) { + v[i%size]++; + } + answer++; + cout << answer << ":"; + FORI(size) + cout << " " << v[i]; + cout << endl; + } + cout << (-seen[h] + answer) << endl; // Just use answer for Part 1 +} diff --git a/aoc2017/P07.cpp b/aoc2017/P07.cpp new file mode 100644 index 0000000..035f6af --- /dev/null +++ b/aoc2017/P07.cpp @@ -0,0 +1,76 @@ +// RM (),-> from input + +struct P { + string name; + int weight, full; + vector children; +}; + +typedef map MAP; +MAP m; + +int weight(string name) { + P *p = m[name]; + if(p->full >= 0) + return p->full; // Done. + FORIT(vector, p->children) { + weight(*it); + } + p->full = p->weight; + FORIT(vector, p->children) { + p->full += m[*it]->full; + } + return p->full; +} + +int main() { + set hasParent; + string s; + while(getline(cin, s)) { + stringstream ss; ss << s; + P *p = new P; + ss >> p->name >> p->weight; + p->full = -1; + while(ss >> s) { + p->children.push_back(s); + hasParent.insert(s); + } + if(p->children.empty()) { + p->full = p->weight; + } + if(p->children.size() == 1) { + cerr << "Oh no! 1 child!" << endl; + } + m[p->name] = p; + } + + FORIT(MAP, m) { + string name = it->first; + if(hasParent.find(name) == hasParent.end()) { + cout << "Answer 1: " << name << endl; + } + } + + // Part 2 computation: + FORIT(MAP, m) { + P *p = it->second; + if(p->children.empty()) { + continue; // No children + } + vector v; + FORIT(vector, p->children) { + v.push_back(PIS(weight(*it), *it)); + } + sort(v.begin(), v.end()); + if(v[0].first != v[1].first) { + string toFix = v[0].second, ok = v[1].second; + int diff = v[1].first-v[0].first; + cout << "START Answer 2: " << (m[toFix]->weight - diff) << endl; + } + if(v[v.size()-1].first != v[0].first) { + string toFix = v[v.size()-1].second, ok = v[0].second; + int diff = v[v.size()-1].first-v[0].first; + cout << p->name << " END Answer 2: " << (m[toFix]->weight - diff) << " fix of " << m[toFix]->name << endl; + } + } +} diff --git a/aoc2017/P08.cpp b/aoc2017/P08.cpp new file mode 100644 index 0000000..349a454 --- /dev/null +++ b/aoc2017/P08.cpp @@ -0,0 +1,67 @@ +typedef map MAP; +MAP m; + +string s, reg1, op1, reg2, op2; +LL v1, v2; + +LL get(string ®) { + if(m.find(reg) == m.end()) { + return 0; + } + return m[reg]; +} + +bool check() { + LL vReg = get(reg2); + if(op2 == "==") { + return vReg == v2; + } + else if(op2 == "!=") { + return vReg != v2; + } + else if(op2 == "<=") { + return vReg <= v2; + } + else if(op2 == ">=") { + return vReg >= v2; + } + else if(op2 == "<") { + return vReg < v2; + } + else if(op2 == ">") { + return vReg > v2; + } + else { + cerr << "Unknown op2: " << op2 << endl; + die(); + return false; + } +} + +int main() { + LL ma2 = -99999999; + while(cin >> reg1 >> op1 >> v1 >> s >> reg2 >> op2 >> v2) { + if(check()) { + if(op1 == "dec") { + m[reg1] = get(reg1) - v1; + } + else if(op1 == "inc") { + m[reg1] = get(reg1) + v1; + } + else { + cerr << "Unknown op1: " << op1 << endl; + die(); + } + ma2 = max(ma2, m[reg1]); + } + else { + cout << "SKIP " << reg1 << " " << op1 << " " << v1 << " " << s << " " << reg2 << " " << op2 << " " << v2 << endl; + } + } + LL ma = -9999999; + FORIT(MAP, m) { + ma = max(ma, it->second); + } + cout << ma << endl; + cout << ma2 << endl; +} diff --git a/aoc2017/P09.cpp b/aoc2017/P09.cpp new file mode 100644 index 0000000..2c4a1c8 --- /dev/null +++ b/aoc2017/P09.cpp @@ -0,0 +1,37 @@ +int main() { + GS(s); + LL lv = 0, answer1 = 0, answer2 = 0; + bool inGarbage = false; + FORUI(s.size()) { + char c = s[i]; + if(inGarbage) { + switch(c) { + case '>': + inGarbage = false; + break; + case '!': + i++; // skip next + break; + default: + answer2++; + break; + } + } // if inGarbage + else { + switch(c) { + case '<': + inGarbage = true; + break; + case '{': + lv++; + answer1 += lv; + break; + case '}': + lv--; + break; + } + } // not in garbage + } // FORUI s + cout << answer1 << endl; + cout << answer2 << endl; +} diff --git a/aoc2017/P10.cpp b/aoc2017/P10.cpp new file mode 100644 index 0000000..f3edbc1 --- /dev/null +++ b/aoc2017/P10.cpp @@ -0,0 +1,49 @@ +// Replace commas with spaces in input and prefix with size for Part 1. For part 2, keep input. +int main() { + int size = 256; + int v[256]; + FORI(size) { + v[i] = i; + } + int x, pos = 0, skipSize = 0; + // Part 2 input processing: + GS(input); + vector v1; + FORUI(input.size()) { + v1.push_back((int)input[i]); + } + v1.push_back(17); + v1.push_back(31); + v1.push_back(73); + v1.push_back(47); + v1.push_back(23); + // For part 1, ignore these 5 above and don't add '0'. + + FORK(64) { // 1 for Part 1 + FORIT(vector, v1) { + x = *it; + for(int i = pos, j = pos+x-1; i < j; i++, j--) { + swap(v[i%size],v[(j+size)%size]); + } + pos = (pos + x + skipSize)%size; + skipSize++; + //FORI(size) + // cout << " " << v[i]; + //cout << endl; + } + } + + // Compute dense hash: + printf("Dense hash:\n"); + uint8_t y = 0; + FORI(size) { + y = y ^ v[i]; + if(i%16 == 15) { + printf("%02x",y); + y = 0; + } + } + printf("\n"); + //cout << (v[0]*v[1]) << endl; // Part 1 + +} diff --git a/aoc2017/P11.cpp b/aoc2017/P11.cpp new file mode 100644 index 0000000..5c36942 --- /dev/null +++ b/aoc2017/P11.cpp @@ -0,0 +1,53 @@ +int dist(PI p) { + // Get back to 0,0: + int ret = 0; + int dirX = p.XX > 0 ? -1 : 1; + while(p.XX != 0) { + if(p.XX % 2 == 0) { + if(p.YY > 0) + p.YY--; + } + else { + if(p.YY < 0) + p.YY++; + } + p.XX+=dirX; + ret++; + } + ret += abs(p.YY); + return ret; +} + +// Replace comma with space in input. +int main() { + PI p(0,0); + string s; + int answer2 = -1; + while(cin >> s) { + if(s == "s") { + p.YY++; + continue; + } + if(s == "n") { + p.YY--; + continue; + } + + if(p.XX % 2 == 0) { + if(s[0] == 'n') + p.YY--; + } + else { + if(s[0] == 's') + p.YY++; + } + if(s[1] == 'e') + p.XX--; + else // w: + p.XX++; + answer2 = max(answer2, dist(p)); + } + + cout << "Answer 1: " << dist(p) << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2017/P12.cpp b/aoc2017/P12.cpp new file mode 100644 index 0000000..d52b6b4 --- /dev/null +++ b/aoc2017/P12.cpp @@ -0,0 +1,44 @@ +// Remove comma from input +set neighbours[2000]; + +int main() { + string s; + + int size = 0, a, b; + while(getline(cin, s)) { + stringstream ss; ss << s; + ss >> a >> s; + while(ss >> b) { + neighbours[a].insert(b); + neighbours[b].insert(a); + } + size++; + } + // Comput group with 0: + set seen; + int groups = 0; + for(int x = 0; x < size; x++) { + if(seen.find(x) != seen.end()) + continue; // Already handled + + stack ready; + ready.push(x); + while(!ready.empty()) { + int x = ready.top(); ready.pop(); + if(seen.find(x) != seen.end()) + continue; // Already handled + seen.insert(x); + FORIT(set, neighbours[x]) { + int y = *it; + if(seen.find(y) == seen.end()) { + ready.push(y); + } + } + } + if(groups == 0) + cout << "Answer 1: " << seen.size() << endl; + + groups++; + } + cout << "Answer 2: " << groups << endl; +} diff --git a/aoc2017/run.sh b/aoc2017/run.sh new file mode 100755 index 0000000..fff7fb7 --- /dev/null +++ b/aoc2017/run.sh @@ -0,0 +1,37 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2017/top.cpp b/aoc2017/top.cpp new file mode 100644 index 0000000..41a5f17 --- /dev/null +++ b/aoc2017/top.cpp @@ -0,0 +1,73 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2018/P01.cpp b/aoc2018/P01.cpp new file mode 100644 index 0000000..648be1e --- /dev/null +++ b/aoc2018/P01.cpp @@ -0,0 +1,20 @@ +// RM + from input +int main() { + LL a = 0, b; + set s; + vector v; + while(cin >> b) { + v.push_back(b); + } + cout << "Read " << v.size() << " changes" << endl; + for(int i = 0; true; i++) { + b = v[i%v.size()]; + a += b; + if(s.find(a) != s.end()) { + cout << "Answer 2: " << a << endl; + return 0; // Part 2 only + } + s.insert(a); + } + //cout << a << endl; // Part 1 only +} diff --git a/aoc2018/P02.cpp b/aoc2018/P02.cpp new file mode 100644 index 0000000..d235a24 --- /dev/null +++ b/aoc2018/P02.cpp @@ -0,0 +1,48 @@ +int main() { + int a[26]; string s; + int with2 = 0, with3 = 0; + vector v; + while(cin >> s) { + v.push_back(s); + FORI(26) a[i] = 0; + FORUI(s.size()) { + a[s[i]-'a']++; + } + bool has2 = false, has3 = false; + FORI(26) { + if(a[i] == 2) + has2 = true; + else if(a[i] == 3) + has3 = true; + } + if(has2) + with2++; + if(has3) + with3++; + } + cout << "Answer 1: " << (with2*with3) << endl; + + // Part 2: + FORI((int)v.size()-1) { + for(int j = i+1; j < v.size(); j++) { + string s1 = v[i], s2 = v[j]; + int differences = 0; + int diffAt; + FORUK(s1.size()) { + if(s1[k] != s2[k]) { + differences++; + diffAt = k; + } + } + if(differences == 1) { + cout << "Answer 2: " << endl; + FORUK(s1.size()) { + if(k != diffAt) + cout << s1[k]; + } + cout << endl; + return 0; + } + } + } +} diff --git a/aoc2018/P03.cpp b/aoc2018/P03.cpp new file mode 100644 index 0000000..054fa0e --- /dev/null +++ b/aoc2018/P03.cpp @@ -0,0 +1,56 @@ +#define SIZE 1001 +// Replace [,:x@#] with space in input +int main() { + int Q[SIZE][SIZE]; + FORI(SIZE) { + FORJ(SIZE) + Q[i][j] = 0; + } + + vector v; + int id, a, b, c, d, miX = 9999, miY = 9999, maX = -999, maY = -999; + while(cin >> id >> a >> b >> c >> d) { + v.push_back(PI4(PI(a,b),PI(c,d))); + miX = min(miX, a); + miY = min(miY, b); + maX = max(maX, a+c); + maY = max(maY, b+d); + for(int x = a; x < a+c; x++) { + for(int y = b; y < b+d; y++) { + Q[y][x]++; + } + } + } + cout << "Read " << v.size() << " claims, spanning over " << miX << "," << miY << " -> " << maX << "," << maY << endl; + int answer1 = 0; + FORI(SIZE) { + FORJ(SIZE) { + if(Q[i][j] > 1) { + answer1++; + } + } + } + cout << "Answer 1: " << answer1 << endl; + // Part 2: Find free claim: + id = 1; + FORIT(vector, v) { + a = it->first.XX; + b = it->first.YY; + c = it->second.XX; + d = it->second.YY; + bool ok = true; + for(int x = a; ok && x < a+c; x++) { + for(int y = b; y < b+d; y++) { + if(Q[y][x] != 1) { + ok = false; + break; + } + } + } + if(ok) { + cout << "Answer 2: " << id << endl; + return 0; + } + id++; + } +} diff --git a/aoc2018/P04.cpp b/aoc2018/P04.cpp new file mode 100644 index 0000000..f4a6e43 --- /dev/null +++ b/aoc2018/P04.cpp @@ -0,0 +1,134 @@ +// RM "Guard #" and "[1518-". Replace :-] with space +int cntOnes(ULL x) { + int ret = 0; + while(x > 0) { + if((x & 1) == 1) { + ret++; + } + x >>= 1; + } + return ret; +} +typedef map MAP; +int main() { + // Sort input: + vector v; + string s; + while(getline(cin, s)) { + v.push_back(s); + } + sort(v.begin(), v.end()); + + // Analyse: + vector v2; // id -> asleep + MAP m; // id -> total sleep + + int month = -1, day = -1, hour = -1, minute = -1, guard = -1; + ULL sleep = 0; + FORIT(vector, v) { + stringstream ss; ss << *it; + //cout << *it << endl; + ss >> month >> day >> hour >> minute >> s; + if(s == "falls") { + if(hour != 0) { + cerr << "Unexpected hour: " << hour << endl; + die(); + } + for(int i = minute; i <= 59; i++) { + sleep |= ((ULL)1 << i); + } + } + else if(s == "wakes") { + if(hour != 0) { + cerr << "Unexpected hour: " << hour << endl; + die(); + } + for(int i = minute; i <= 59; i++) { + sleep &= ~((ULL)1 << i); + } + } + else { + if(guard != -1) { + cout << guard << ": " << bitset<60>(sleep) << endl; + v2.push_back(PULL(guard,sleep)); + m[guard]+=cntOnes(sleep); + } + + guard = stoi(s); + if(m.find(guard) == m.end()) + m[guard] = 0; + sleep = 0; + if(hour != 0) { + day++; + } + } + } + cout << guard << ": " << bitset<60>(sleep) << endl; + v2.push_back(PULL(guard,sleep)); + m[guard]+=cntOnes(sleep); + + // Find sleepiest guard: + int bestGuard = -1; + int bestSleep = -1; + FORIT(MAP, m) { + if(bestSleep < it->second) { + bestGuard = it->first; + bestSleep = it->second; + } + } + cout << "Guard to kill: " << bestGuard << endl; + // Find when to kill: + int minutes[60]; + FORI(60) + minutes[i] = 0; + + FORIT(vector, v2) { + if(it->first != bestGuard) { + continue; // Not our guy! + } + ULL bits = it->second; + FORI(60) { + if((bits & 1) == 1) { + minutes[i]++; + } + bits >>= 1; + } + } + int bestMinute = -1; + int mostSleep = -1; + FORI(60) { + if(minutes[i] > mostSleep) { + bestMinute = i; + mostSleep = minutes[i]; + } + } + cout << "Most sleep at minute " << bestMinute << ": " << mostSleep << endl; + cout << "Answer 1: " << (bestGuard * bestMinute) << endl; + + // Part 2: + bestMinute = -1; + int sleepAtMinute = -1; + int guardAtMinute = -1; + FORI(60) { // minute i + FORIT(MAP, m) { // Try each guard: + int guard = it->first; + int sleep = 0; + FORIT(vector, v2) { // See if they slept: + if(it->first != guard) { + continue; // Not our guy! + } + ULL bits = it->second; + if(((bits >> i) & 1) == 1) { + sleep++; + } + } + if(sleep > sleepAtMinute) { + bestMinute = i; + sleepAtMinute = sleep; + guardAtMinute = guard; + } + } + } + cout << "Guard " << guardAtMinute << " Sleeps " << sleepAtMinute << " at " << bestMinute << endl; + cout << "Answer 2: " << (guardAtMinute * bestMinute) << endl; +} diff --git a/aoc2018/P05.cpp b/aoc2018/P05.cpp new file mode 100644 index 0000000..e077444 --- /dev/null +++ b/aoc2018/P05.cpp @@ -0,0 +1,41 @@ +bool kill(char a, char b) { + if(a > b) + swap(a,b); + a += 'a'-'A'; + return a == b; +} + +int react(string &input, int size) { + stack s; + FORUI(size) { + char c = input[i]; + if(s.size() > 0 && kill(s.top(),c)) { + s.pop(); + } + else { + s.push(c); + } + } + return (int)s.size(); +} + +int main() { + GS(s); + cout << "Answer 1: " << react(s, (int)s.size()) << endl; + int best = (int)s.size(); + FORI(26) { + string s2 = s; + int size = 0; + FORUJ(s2.size()) { + char c = s2[j]; + if(c == (char)('a'+i) || c == (char)('A'+i)) { + // Skip! + } + else { + s2[size++] = c; + } + } + best = min(best, react(s2, size)); + } + cout << "Answer 2: " << best << endl; +} diff --git a/aoc2018/P06.cpp b/aoc2018/P06.cpp new file mode 100644 index 0000000..681b1cd --- /dev/null +++ b/aoc2018/P06.cpp @@ -0,0 +1,103 @@ +// Remove commas from input +int Q[1000][1000]; + +int main() { + vector v; + int x, y, miX = 999, miY = 999, maX = -1, maY = -1; + while(cin >> x >> y) { + v.push_back(PI(x,y)); + miX = min(miX,x); + miY = min(miY,y); + maX = max(maX,x); + maY = max(maY,y); + } + cout << "Stuff in area " << miX << "," << miY << " -> " << maX << "," << maY << endl; + FORUI((int)v.size()) { + v[i].XX-=miX; + v[i].YY-=miY; + } + maX-=miX; + maY-=miY; + cout << "Now in area 0,0 -> " << maX << "," << maY << endl; + + FORY(maY+1) { + FORX(maX+1) { + int minDist = 99999; + int minIdx; + int cntMin = 0; + int idx = 0; + FORIT(vector, v) { + int dist = abs(x - it->XX) + abs(y - it->YY); + if(dist < minDist) { + minDist = dist; + cntMin = 1; + minIdx = idx; + } + else if(dist == minDist) { + cntMin++; + } + idx++; + } + if(cntMin == 1) { + Q[y][x] = minIdx; + } + else { + Q[y][x] = -1; + } + } + } + + // Print: + FORY(maY+1) { + FORX(maX+1) { + int idx = Q[y][x]; + if(idx == -1) + cout << "."; + else + cout << ((char)('a'+idx)); + } + cout << endl; + } + + int *areaSize = new int[v.size()]; + FORUI(v.size()) { + areaSize[i] = 0; + } + FORY(maY+1) { + FORX(maX+1) { + int idx = Q[y][x]; + if(idx == -1) + continue; + else if(areaSize[idx] == -1) + continue; + else if(x == 0 || x == maX || y == 0 || y == maY) { + areaSize[idx] = -1; + } + else { + areaSize[idx]++; + } + } + } + int largestArea = -1; + FORUI(v.size()) { + cout << "Area size for " << i << ": " << areaSize[i] << endl; + largestArea = max(areaSize[i], largestArea); + } + cout << "Answer 1: " << largestArea << endl; + + // Part 2: + LL maxDist = 10000; + int answer2 = 0; + FORY(maY+1) { + FORX(maX+1) { + LL sumDist = 0; + FORIT(vector, v) { + int dist = abs(x - it->XX) + abs(y - it->YY); + sumDist += dist; + } + if(sumDist <= maxDist) + answer2++; + } + } + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2018/P07.cpp b/aoc2018/P07.cpp new file mode 100644 index 0000000..886a2be --- /dev/null +++ b/aoc2018/P07.cpp @@ -0,0 +1,96 @@ +// RM "must be finished before step ", "Step " and " can begin." from input +// Add time penalty and number of workers to beginning of input +int main() { + GI(penalty); GI(workers); + char c1, c2; + int blockers[26], blockers2[26]; + vector blocking[26]; + set seen; + FORI(26) + blockers[i] = blockers2[i] = 0; + while(cin >> c1 >> c2) { + // c1 blocks c2; + blocking[c1-'A'].push_back(c2); + blockers[c2-'A']++; + blockers2[c2-'A']++; + seen.insert(c1); + seen.insert(c2); + } + set ready, ready2; + FORI(26) { + if(seen.find((char)('A'+i)) != seen.end() && blockers[i] == 0) { + ready.insert((char)('A'+i)); + ready2.insert((char)('A'+i)); + } + } + vector order; + // Part 1: + while(!ready.empty()) { + char c = *ready.begin(); + ready.erase(ready.begin()); + cout << c; + order.push_back(c); + FORIT(vector, blocking[c-'A']) { + char c2 = *it; + blockers[c2-'A']--; + if(blockers[c2-'A'] == 0) { + ready.insert(c2); + } + } + } + cout << endl; + // Part 2: Simulate construction with 5 workers: + int time = 0; + int remainingItems = (int)seen.size(); + int remaining[26]; + FORI(26) { + remaining[i] = penalty + 1 + i; + } + for(; remainingItems > 0; time++) { + if(ready2.empty()) { + cerr << "Nothing to work on!" << endl; + return 2; + } + // Find items that can be worked on: + vector toRemove, toInsert; + // Take those that are finished soonest: + vector v3; + FORIT(set, ready2) { + char c = *it; + v3.push_back(PI(-remaining[c-'A'], c)); + } + sort(v3.begin(), v3.end()); + + int workers2 = 1; + cout << "Time " << time << " working on"; + FORIT(vector, v3) { + if(workers2++ > workers) { + break; // Not enough workers. + } + char c = it->second; + remaining[c-'A']--; + cout << " " << c << " (" << remaining[c-'A'] << ")"; + if(remaining[c-'A'] == 0) { + //cout << "After " << time << ", item " << c << " is done. Reduce blocking for: " << blocking[c-'A'].size() << endl; + toRemove.push_back(c); + FORIT2(vector, blocking[c-'A']) { + char c2 = *it2; + blockers2[c2-'A']--; + if(blockers2[c2-'A'] == 0) { + //cout << "Now ready: " << c2 << endl; + toInsert.push_back(c2); + } + } + remainingItems--; + } + } + cout << endl; + FORIT(vector, toRemove) { + ready2.erase(*it); + } + FORIT(vector, toInsert) { + ready2.insert(*it); + } + } // for ; + cout << "Answer 2: " << time << endl; // [1102 1108] +} diff --git a/aoc2018/P08.cpp b/aoc2018/P08.cpp new file mode 100644 index 0000000..152fe30 --- /dev/null +++ b/aoc2018/P08.cpp @@ -0,0 +1,35 @@ +LL meta = 0; + +LL read() { + GI(c); // children + GI(m); // meta + vector v; + FORI(c) { + v.push_back(read()); + } + LL ret = 0; + FORI(m) { + GI(x); + meta += x; + if(c == 0) + ret +=x; + else { + x--; + if(x < 0 || x >= v.size()) { + // skip! + + } + else { + ret += v[x]; + } + } + + } + return ret; +} + +int main() { + LL answer2 = read(); + cout << "Answer 1: " << meta << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2018/P09.cpp b/aoc2018/P09.cpp new file mode 100644 index 0000000..8135e84 --- /dev/null +++ b/aoc2018/P09.cpp @@ -0,0 +1,77 @@ +struct Marble { + Marble *prev, *next; + int val; +}; + +// Remove all by the numbers from the input! +int main() { + int players, lastMarble; + cin >> players >> lastMarble; + LL *scores = new LL[players]; + FORI(players) + scores[i] = 0; + + Marble *root = new Marble; + root->next = root->prev = root; + root->val = 0; + Marble *cur = root; + + for(int i = 1; i <= lastMarble; i++) { + if(i % 23 == 0) { + scores[i%players]+=i; + // Remove -7 ball! + FORJ(7) { + cur = cur->prev; + } + scores[i%players]+=cur->val; + cur = cur->prev; + cur->next = cur->next->next; + cur->next->prev = cur; + + cur = cur->next; + } + else { + // Insert marble i: + cur = cur->next; // Insert after this. + Marble *next = cur->next; + + Marble *m = new Marble; + m->val = i; + // Update 4 pointers: + m->prev = cur; + m->next = next; + cur->next = next->prev = m; + // Set new cur: + cur = m; + } + + if(i < 30) { + cout << "[" << ((i-1)%players+1) << "] " << root->val; + Marble *m = root->next; + while(m != root) { + if(m != m->next->prev || m->next == m || m->prev == m) { + cerr << "List broken!" << endl; + die(); + } + if(m->val < 10) + cout << " "; + if(m == cur) + cout << "("; + else + cout << " "; + cout << m->val; + if(m == cur) + cout << ")"; + else + cout << " "; + m = m->next; + } + cout << endl; + } + } + LL bestScore = -1; + FORI(players) { + bestScore = max(scores[i], bestScore); + } + cout << bestScore << endl; +} diff --git a/aoc2018/P10.cpp b/aoc2018/P10.cpp new file mode 100644 index 0000000..2916cdd --- /dev/null +++ b/aoc2018/P10.cpp @@ -0,0 +1,63 @@ +#define SIZE 1000 + +// Remove "position=<", "> velocity=<", ",", and ">" from input. +int main() { + vector p, v; + int a, b, c, d; + while(cin >> a >> b >> c >> d) { + p.push_back(PI(a,b)); + v.push_back(PI(c,d)); + //cout << "(" << a << "," << b << ") -> )" << c << "," << d << ")" << endl; + } + int lastW = 9999999, lastH = 9999999; + + bool Q[SIZE][SIZE]; + + FORK(100000) { + FORY(SIZE) { + FORX(SIZE) { + Q[y][x] = false; + } + } + int miX = 9999999, miY = 9999999, maX = -9999999, maY = -9999999; + FORI((int)p.size()) { + int x = p[i].XX + k*v[i].XX; + int y = p[i].YY + k*v[i].YY; + miX = min(miX, x); + maX = max(maX, x); + miY = min(miY, y); + maY = max(maY, y); + } + int w = maX-miX+1; + int h = maY-miY+1; + cout << "Size: " << w << " x " << h << endl; + if(w > lastW && h >lastH) { + return 0; // Done. + } + lastW = w; + lastH = h; + bool ok = true; + FORI((int)p.size()) { + int x = p[i].XX + k*v[i].XX - miX; + int y = p[i].YY + k*v[i].YY - miY; + if(x < SIZE && y < SIZE) + Q[y][x] = true; + else { + ok = false; + break; + } + } + if(ok) { + cout << "Time " << k << endl; + FORY(maY-miY+1) { + FORX(maX-miX+1) { + if(Q[y][x]) + cout << "#"; + else + cout << "."; + } + cout << endl; + } + } + } +} diff --git a/aoc2018/P11.cpp b/aoc2018/P11.cpp new file mode 100644 index 0000000..6eea079 --- /dev/null +++ b/aoc2018/P11.cpp @@ -0,0 +1,49 @@ +int serial; + +LL get(int x, int y) { + LL rackID = x+10; + LL powerLevel = rackID*y; + powerLevel += serial; + powerLevel *= rackID; + powerLevel /= 100; + powerLevel = powerLevel%10; + powerLevel -= 5; + return powerLevel; +} + +int main() { + cin >> serial; + + LL best = -9999999; + int bestX, bestY, bestSize; + for(int y = 1; y <= 300; y++) { + for(int x = 1; x <= 300; x++) { + LL v = get(x,y); + if(v > best) { + bestX = x; + bestY = y; + best = v; + bestSize = 1; + } + for(int size = 2; x + size-1 <= 300 && y + size-1 <= 300; size++) { + int xx = x + size-1; + for(int i = 0; i < size; i++) { + v += get(xx, y+i); + } + int yy = y + size-1; + for(int i = 0; i < size-1; i++) { + v += get(x+i, yy); + } + if(v > best) { + bestX = x; + bestY = y; + best = v; + bestSize = size; + } + } + } + } + + cout << "Best square at top-left " << bestX << "," << bestY << "," << bestSize << endl; + cout << "Best value: " << best << endl; +} diff --git a/aoc2018/P12.cpp b/aoc2018/P12.cpp new file mode 100644 index 0000000..a7289e6 --- /dev/null +++ b/aoc2018/P12.cpp @@ -0,0 +1,71 @@ +// RM "initial state: " from input +#define SIZE 1000 +#define HALF_SIZE SIZE/2 + +bool v[SIZE], w[SIZE]; +typedef map MAP; +MAP m; + +int main() { + FORI(SIZE) + v[i] = w[i] = false; + + string s, ignore; char c; + cin >> s; + FORUI(s.size()) { + if(s[i] == '#') { + v[HALF_SIZE+i] = true; + } + } + while(cin >> s >> ignore >> c) { + m[s] = c == '#'; + } + + // Simulate: + LL addX = 0; + map m2; // encoding, PI(k, mi) + + LL GENS = 50000000000; // 20 for part 1 + //LL GENS = 200; // Use for testing + for(LL k = 0; k < GENS; k++) { + int mi = 9999999, ma = -9999999; + FORI(SIZE) + w[i] = false; + FORI(SIZE-5) { + stringstream ss; + FORK(5) + ss << (v[i+k] ? '#' : '.'); + if(m[ss.str()]) { + w[i+2] = '#'; + mi = min(mi, i+2); + ma = max(ma, i+2); + } + } + swap(v,w); + //cout << "After " << k << ": range " << mi << " -> " << ma << " range size " << (ma-mi+1) << endl; + stringstream ss; + for(int i = mi; i <= ma; i++) { + ss << (v[i] ? '#' : '.'); + } + s = ss.str(); + if(m2.find(s) == m2.end()) { + m2[s] = PI(k, mi); + } + else { + LL lastK = m2[s].first; + LL lastMi = m2[s].second; + cout << "Duplicate found! " << s << endl; + cout << "generation now: " << k << ", then: " << lastK << endl; + cout << "Starts at now: " << mi << ", then: " << lastMi << endl; + addX = GENS-k-1; + break; + }//*/ + } + + LL answer1 = 0; + FORI(SIZE) { + if(v[i]) + answer1+=i+addX-HALF_SIZE; + } + cout << answer1 << endl; +} diff --git a/aoc2018/run.sh b/aoc2018/run.sh new file mode 100755 index 0000000..fff7fb7 --- /dev/null +++ b/aoc2018/run.sh @@ -0,0 +1,37 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2018/top.cpp b/aoc2018/top.cpp new file mode 100644 index 0000000..3e1a9fd --- /dev/null +++ b/aoc2018/top.cpp @@ -0,0 +1,74 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PI4; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2019/P01.cpp b/aoc2019/P01.cpp new file mode 100644 index 0000000..2fa308e --- /dev/null +++ b/aoc2019/P01.cpp @@ -0,0 +1,12 @@ +int main() { + LL sum = 0; + int x; + while(cin >> x) { + x = (x/3)-2; + while(x > 0) { + sum += x; + x = (x/3)-2; // Part 2 + } + } + cout << sum << endl; +} diff --git a/aoc2019/P02.cpp b/aoc2019/P02.cpp new file mode 100644 index 0000000..66c5d37 --- /dev/null +++ b/aoc2019/P02.cpp @@ -0,0 +1,44 @@ +// replace , with space in input +int main() { + LL w[10000], v[10000]; + int size = 0, x; + while(cin >> x) { + w[size++] = x; + } + w[1] = 12; + w[2] = 2; + + FORX(100) { + FORY(100) { + FORI(size) + v[i] = w[i]; + v[1] = x; + v[2] = y; + int idx = 0; + + while(true) { + if(v[idx] == 1) { + v[v[idx+3]] = v[v[idx+1]] + v[v[idx+2]]; + idx+=4; + } + else if(v[idx] == 2) { + v[v[idx+3]] = v[v[idx+1]] * v[v[idx+2]]; + idx+=4; + } + else if(v[idx] == 99) { + break; + } + else { + die(); + } + //FORI(size) {cout << " " << v[i];}cout << endl; + } + if(19690720 == v[0]) { + cout << "Answer 2: " << (100*x + y) << endl; + return 0; + } + + //cout << "Answer 1: " << v[0] << endl; // Remove the x and y stuff for part 1 + } + } +} diff --git a/aoc2019/P03.cpp b/aoc2019/P03.cpp new file mode 100644 index 0000000..7e94f64 --- /dev/null +++ b/aoc2019/P03.cpp @@ -0,0 +1,58 @@ +typedef map MAP; +MAP s1, s2; + +void build(string &line, MAP &S) { + stringstream ss; ss << line; + char c; + int x, steps = 1; + PI p(0,0); + while(ss >> c >> x) { + while(x > 0) { + switch(c) { + case 'U': + p.YY--; + break; + case 'D': + p.YY++; + break; + case 'L': + p.XX--; + break; + case 'R': + p.XX++; + break; + } + if(S.find(p) == S.end()) + S[p] = steps; + x--; + steps++; + } + } + +} + +int main() { + string line; + getline(cin, line); + build(line, s1); + getline(cin, line); + build(line, s2); + int answer1 = 9999999; + int answer2 = 9999999; + FORIT(MAP, s1) { + PI p = it->first; + if(s2.find(p) != s2.end()) { + int dist = abs(p.XX) + abs(p.YY); + if(dist > 0) { + answer1 = min(answer1, dist); + + int d1 = it->second; + int d2 = s2[p]; + cout << "Intersection " << p.XX << "," << p.YY << " after " << d1 << " and " << d2 << " steps" << endl; + answer2 = min(answer2, d1+d2); + } + } + } + cout << answer1 << endl; + cout << answer2 << endl; +} diff --git a/aoc2019/P04.cpp b/aoc2019/P04.cpp new file mode 100644 index 0000000..4428c3c --- /dev/null +++ b/aoc2019/P04.cpp @@ -0,0 +1,31 @@ +bool ok(int x) { + int prev = 99; + int digits[6]; + FORI(6) { + int digit = x % 10; + digits[i] = digit; + if(prev < digit) + return false; + x /= 10; + prev = digit; + } + // Find pair: + FORI(5) { + if(digits[i] == digits[i+1]) { + bool lowOK = i == 0 || digits[i-1]!=digits[i]; + bool highOK = i+2 > 5 || digits[i+2]!=digits[i]; + if(lowOK && highOK) + return true; + } + } + return false; +} + +int main() { + GI(low); GI(high); int answer1 = 0; + for(int i = low; i <= high; i++) { + if(ok(i)) + answer1++; + } + cout << answer1 << endl; +} diff --git a/aoc2019/P05.cpp b/aoc2019/P05.cpp new file mode 100644 index 0000000..0496e54 --- /dev/null +++ b/aoc2019/P05.cpp @@ -0,0 +1,119 @@ +#define SIZE 100000 +LL v[SIZE]; +vector input, output; +int inputIdx = 0, size = 0; + +LL getInput() { + return input[inputIdx++]; +} + +void out(LL x) { + output.push_back(x); + cout << "Output: " << x << endl; +} + +LL get(vector &modes, int param, int idx) { + int mode = param-1 < modes.size() ? modes[param-1] : 0; + if(idx+param < 0 || idx+param >= size) { + cerr << "Parameter out of bounds: " << idx << " + " << param << endl; + die(); + } + LL x = v[idx+param]; + if(mode == 1) { // 1 => immediate mode + return x; + } + else { // 0 => position mode + if(x < 0 || x >= size) { + cerr << "Position mode parameter out of bounds: " << x << endl; + die(); + } + return v[x]; + } +} + +// replace , with space in input +int main() { + LL x; + while(cin >> x) { + v[size++] = x; + } + + input.push_back(5); // 1 for part 1, 5 for part 2. + + int idx = 0; + cout << "Setup complete" << endl; + + while(true) { + int opcode = v[idx]%100; + //cout << "OP " << opcode; + int modeBits = v[idx]/100; + vector modes; + while(modeBits > 0) { + //cout << " " << modeBits%2; + modes.push_back(modeBits % 2); + modeBits/=10; + } + //cout << endl; + + if(opcode == 1) { + LL val = get(modes, 1, idx) + get(modes, 2, idx); + //cerr << "Setting value " << val << " to position " << v[idx+3] << endl; + v[v[idx+3]] = val; + idx+=4; + } + else if(opcode == 2) { + v[v[idx+3]] = get(modes, 1, idx) * get(modes, 2, idx); + idx+=4; + } + else if(opcode == 3) { + v[v[idx+1]] = getInput(); + cout << "Reading input " << v[v[idx+1]] << endl; + idx+=2; + } + else if(opcode == 4) { + out(get(modes, 1, idx)); + idx+=2; + } + else if(opcode == 5) { + LL check = get(modes, 1, idx); + LL pointer = get(modes, 2, idx); + if(check != 0) { + cout << "Jump !0 " << pointer << endl; + idx = pointer; + } + else { + idx+=3; + } + } + else if(opcode == 6) { + LL check = get(modes, 1, idx); + LL pointer = get(modes, 2, idx); + if(check == 0) { + cout << "Jump 0 " << pointer << endl; + idx = pointer; + } + else { + idx+=3; + } + } + else if(opcode == 7) { + LL p1 = get(modes, 1, idx); + LL p2 = get(modes, 2, idx); + v[v[idx+3]] = p1 < p2 ? 1 : 0; + idx+=4; + } + else if(opcode == 8) { + LL p1 = get(modes, 1, idx); + LL p2 = get(modes, 2, idx); + v[v[idx+3]] = p1 == p2 ? 1 : 0; + idx+=4; + } + else if(opcode == 99) { + break; + } + else { + cerr << "Unknown opcode: " << opcode << endl; + die(); + } + } +} diff --git a/aoc2019/P06.cpp b/aoc2019/P06.cpp new file mode 100644 index 0000000..70268f8 --- /dev/null +++ b/aoc2019/P06.cpp @@ -0,0 +1,36 @@ +// Replace ) with space in input. +typedef map MAP; +int main() { + MAP m; + string a, b; + while(cin >> a >> b) { + m[b] = a; + } + int answer1 = 0; + FORIT(MAP, m) { + string planet = it->first; + answer1++; + string parent = it->second; + while(parent != "COM") { + parent = m[parent]; + answer1++; + } + } + cout << "Answer 1: " << answer1 << endl; + + // Part 2: YOU -> SAN + map dists; + int dist = 0; + string you = "YOU"; + while(you != "COM") { + dists[you] = dist++; + you = m[you]; + } + string san = "SAN"; + dist = 0; + while(dists.find(san) == dists.end()) { + san = m[san]; + dist++; + } + cout << "Answer 2: " << (dist + dists[san] - 2) << endl; +} diff --git a/aoc2019/P07.cpp b/aoc2019/P07.cpp new file mode 100644 index 0000000..d0337f7 --- /dev/null +++ b/aoc2019/P07.cpp @@ -0,0 +1,215 @@ +#define SIZE 10000 + +LL w[SIZE]; +int size = 0; + +struct Amplifier { + LL v[SIZE]; + int idx; + int inputIdx; + + Amplifier() { + idx = 0; + inputIdx = 0; + FORI(size) { + v[i] = w[i]; + } + } + + LL get(vector &modes, int param, int i) { + int mode = param-1 < modes.size() ? modes[param-1] : 0; + if(i+param < 0 || i+param >= size) { + cerr << "Parameter out of bounds: " << i << " + " << param << endl; + die(); + } + LL x = v[i+param]; + if(mode == 1) { // 1 => immediate mode + return x; + } + else { // 0 => position mode + if(x < 0 || x >= size) { + cerr << "Position mode parameter out of bounds: " << x << endl; + die(); + } + return v[x]; + } + } + + LL run(LL input1, LL input2, bool &halt) { + halt = false; + //idx = 0; + LL input[2] = {input1, input2}; + //inputIdx = 0; + cout << "run " << input1 << ", " << input2 << endl; + + while(true) { + int opcode = v[idx]%100; + int modeBits = v[idx]/100; + vector modes; + while(modeBits > 0) { + modes.push_back(modeBits % 2); + modeBits/=10; + } + /*cout << "Run OPCODE " << opcode << " on " << endl; + FORK(size) { + if(k == idx) + cout << " ("; + else + cout << " "; + cout << v[k]; + if(k == idx) + cout << ")"; + } + cout << endl;//*/ + + if(opcode == 1) { + LL val = get(modes, 1, idx) + get(modes, 2, idx); + v[v[idx+3]] = val; + idx+=4; + } + else if(opcode == 2) { + LL val = get(modes, 1, idx) * get(modes, 2, idx); + v[v[idx+3]] = val; + idx+=4; + } + else if(opcode == 3) { + LL val; + if(inputIdx > 0) { + val = input[1]; // Not clearly stated in problem definition! + } + else { + val = input[0]; + inputIdx++; + } + + v[v[idx+1]] = val; + //cout << "Reading input value " << val << " into " << v[idx+1] << endl; + idx+=2; + } + else if(opcode == 4) { + idx+=2; + return get(modes, 1, idx-2); + } + else if(opcode == 5) { + LL check = get(modes, 1, idx); + LL pointer = get(modes, 2, idx); + if(check != 0) { + idx = pointer; + } + else { + idx+=3; + } + } + else if(opcode == 6) { + LL check = get(modes, 1, idx); + LL pointer = get(modes, 2, idx); + if(check == 0) { + idx = pointer; + } + else { + idx+=3; + } + } + else if(opcode == 7) { + LL p1 = get(modes, 1, idx); + LL p2 = get(modes, 2, idx); + v[v[idx+3]] = p1 < p2 ? 1 : 0; + idx+=4; + } + else if(opcode == 8) { + LL p1 = get(modes, 1, idx); + LL p2 = get(modes, 2, idx); + v[v[idx+3]] = p1 == p2 ? 1 : 0; + idx+=4; + } + else if(opcode == 99) { + halt = true; + return 0; + } + else { + cerr << "Unknown opcode: " << opcode << endl; + die(); + } + } + } +}; + +struct PermutationNode { + PermutationNode *next; + int val; +}; +struct PermutationHandler { + PermutationNode *nodes; + PermutationHandler(int size) { + nodes = new PermutationNode[size+1]; + for(int i = 0; i < size; ++i) { + nodes[i+1].val = i+5; // Without +5 for part 1 + nodes[i].next = &(nodes[i+1]); + } + nodes[size].next = NULL; + } + ~PermutationHandler() { + delete[] nodes; + } + PermutationNode* root() { + return &(nodes[0]); + } +}; + +LL best = -99999999; +int phase[5]; + +void go(PermutationHandler &ph, const int i) { + if(i == 5) { + // RUN: + set seen; + cout << "Trying permutation:"; + FORJ(5) { + cout << " " << phase[j]; + } + cout << endl; + + LL input = 0; + Amplifier amps[5]; + bool halted; + while(seen.find(input) == seen.end()) { // For part 1, only run once. + seen.insert(input); + FORJ(5) { + LL x = amps[j].run(phase[j], input, halted); + if(halted) + break; + input = x; + } + best = max(best, input); + cout << " LOOP -> " << input << endl; + } + cout << "Permutation -> " << input << " seen before" << endl; + return; + } + // try all combinations: + PermutationNode *node = ph.root(); + while(node->next != NULL) { + PermutationNode *n = node->next; + // remove n from phaseutation: + node->next = n->next; + + phase[i] = n->val; + go(ph, i+1); + + // re-insert in phaseutation and go to next: + node->next = n; // n->next is already set (never changes) + node = n; + } +} + +// replace , with space in input +int main() { + LL x; + while(cin >> x) { + w[size++] = x; + } + + PermutationHandler ph(5); + go(ph, 0); + cout << "Answer: " << best << endl; +} diff --git a/aoc2019/P08.cpp b/aoc2019/P08.cpp new file mode 100644 index 0000000..7d3253c --- /dev/null +++ b/aoc2019/P08.cpp @@ -0,0 +1,59 @@ +#define WIDTH 25 +#define HEIGHT 6 + +int main() { + int numDigits[1000][10]; // layer, count digit + int image[HEIGHT][WIDTH]; + FORY(HEIGHT) { + FORX(WIDTH) + image[y][x] = 2; // trans + } + + GS(s); + // Part 2: + int idx = 0; + while(idx < (int)s.size()) { + FORY(HEIGHT) { + FORX(WIDTH) { + int pixel = s[idx++]-'0'; + if(pixel == 2) + continue; + if(image[y][x] != 2) + continue; + image[y][x] = pixel; + } + } + } + + FORY(HEIGHT) { + FORX(WIDTH) { + if(image[y][x] == 1) + cout << "#"; + else + cout << " "; + } + cout << endl; + } + + /* Part 1: + int layer = 0; + FORJ(10) + numDigits[0][j] = 0; + + int layerWithMin0 = 0; + FORUI(s.size()) { + int digit = s[i]-'0'; + numDigits[layer][digit]++; + if(WIDTH*HEIGHT-1 == i%(WIDTH*HEIGHT)) { + if(numDigits[layer][0] < numDigits[layerWithMin0][0]) { + layerWithMin0 = layer; + } + layer++; + FORJ(10) { + numDigits[layer][j] = 0; + } + } + } // FORUI s.size() + cout << "Answer 1: " << (numDigits[layerWithMin0][1]*numDigits[layerWithMin0][2]) << endl; + */ +} diff --git a/aoc2019/P09.cpp b/aoc2019/P09.cpp new file mode 100644 index 0000000..a4358c6 --- /dev/null +++ b/aoc2019/P09.cpp @@ -0,0 +1,140 @@ +#define SIZE 50000000 +LL v[SIZE]; +vector input, output; +int inputIdx = 0, size = 0, relativeBase = 0, idx = 0; + +LL getInput() { + if(inputIdx >= 1) + die(); + return input[inputIdx++]; +} + +void out(LL x) { + output.push_back(x); + cout << "Output: " << x << endl; +} + +int getIndex(vector &modes, int param) { + int mode = param-1 < modes.size() ? modes[param-1] : 0; + if(idx+param < 0 || idx+param >= SIZE) { + cerr << "PARAM RANGE " << idx << "+" << param << endl; + die(); + } + + if(mode == 1) { // 1 => immediate mode + return idx+param; + } + LL x = v[idx+param]; + if(mode == 2) { // 2 => relative mode + if(relativeBase + x < 0 || relativeBase+x >= SIZE) { + cerr << "RELATIVE PARAM RANGE " << relativeBase << "+" << x << endl; + die(); + } + return relativeBase + x; + } + else { // 0 => position mode + if(x < 0 || x >= SIZE) { + cerr << "POSITION PARAM RANGE " << x << " from " << idx << ", param " << param << endl; + die(); + } + return x; + } +} + +LL get(vector &modes, int param) { + return v[getIndex(modes, param)]; +} + +void put(vector &modes, int param, LL val) { + v[getIndex(modes, param)] = val; +} + +// replace , with space in input +int main() { + LL x; + FORI(SIZE) { + v[i] = 0; + } + while(cin >> x) { + v[size++] = x; + } + + input.push_back(2); // 1 for part 1 + + cout << "Setup complete" << endl; + + while(true) { + int opcode = v[idx]%100; + //cout << idx << " OP " << opcode << " parameter modes:"; + int modeBits = v[idx]/100; + vector modes; + while(modeBits > 0) { + //cout << " " << modeBits%10; + modes.push_back(modeBits % 10); + modeBits/=10; + } + //cout << endl; + + if(opcode == 1) { + LL val = get(modes, 1) + get(modes, 2); + //cerr << "Putting value " << val << " to position " << v[idx+3] << endl; + put(modes, 3, val); + idx+=4; + } + else if(opcode == 2) { + LL val = get(modes, 1) * get(modes, 2); + put(modes, 3, val); + idx+=4; + } + else if(opcode == 3) { + put(modes, 1, getInput()); + idx+=2; + } + else if(opcode == 4) { + out(get(modes, 1)); + idx+=2; + } + else if(opcode == 5) { + LL check = get(modes, 1); + LL pointer = get(modes, 2); + if(check != 0) { + idx = pointer; + } + else { + idx += 3; + } + } + else if(opcode == 6) { + LL check = get(modes, 1); + if(check == 0) { + idx = get(modes, 2); + } + else { + idx += 3; + } + } + else if(opcode == 7) { + LL p1 = get(modes, 1); + LL p2 = get(modes, 2); + put(modes, 3, p1 < p2 ? 1 : 0); + idx+=4; + } + else if(opcode == 8) { + LL p1 = get(modes, 1); + LL p2 = get(modes, 2); + put(modes, 3, p1 == p2 ? 1 : 0); + idx+=4; + } + else if(opcode == 9) { + relativeBase += get(modes, 1); + idx+=2; + } + else if(opcode == 99) { + break; + } + else { + cerr << "Unknown opcode: " << opcode << endl; + die(); + } + } +} diff --git a/aoc2019/P10.cpp b/aoc2019/P10.cpp new file mode 100644 index 0000000..112ef93 --- /dev/null +++ b/aoc2019/P10.cpp @@ -0,0 +1,96 @@ +typedef pair PDI; + +int gcd(int a, int b) { + int c; + while(a != 0) { + c = a; + a = b%a; + b = c; + } + return b; +} + +double distSQ(PI &a, PI &b) { + double dx = a.XX-b.XX; + double dy = a.YY-b.YY; + return dx*dx+dy*dy; +} + +int main() { + vector v; + + string s; + int y = 0; + while(getline(cin, s)) { + FORUX(s.size()) { + if(s[x] == '#') { + v.push_back(PI(x,y)); + } + } + y++; + } + + int best = 0; + int bestI; + FORUI(v.size()) { + set angles; + FORUJ(v.size()) { + if(i ==j) + continue; + int dx = v[j].XX-v[i].XX; + int dy = v[j].YY-v[i].YY; + int g = gcd(abs(dx),abs(dy)); + dx/=g; + dy/=g; + angles.insert(PI(dx,dy)); + } + if((int)angles.size() > best) { + best = (int)angles.size(); + bestI = i; + } + } + cout << "Answer 1: " << best << endl; + + PI q = v[bestI]; + cout << endl << q.XX << "," << q.YY << endl; + PDI *v2 = new PDI[v.size()]; // angle, idx + int sizeV2 = 0; + FORUJ(v.size()) { + if(j == bestI) + continue; + int dx = v[j].XX-q.XX; + int dy = v[j].YY-q.YY; + int g = gcd(abs(dx),abs(dy)); + dx/=g; + dy/=g; + double angle = atan2(dy,dx) + M_PI/2; + if(angle < 0) + angle += 2*M_PI; + v2[sizeV2++] = PDI(PD(angle,distSQ(q,v[j])), j); + } + sort(v2, v2+sizeV2); + FORI(sizeV2) { + PDI w = v2[i]; + cout << "angle " << w.first.first << " dist " << w.first.second << " " << v[w.second].XX << "," << v[w.second].YY << endl; + } + int idx = 0; + int cnt = 1; + while(cnt <= 200) { + double angle = v2[idx].first.first; + int x = v[v2[idx].second].XX; + int y = v[v2[idx].second].YY; + cout << cnt++ << "= " << x << "," << y << " -> " << (100*x+y) << endl; + + // Erase idx from v2: + for(int k = idx; k+1 < sizeV2; k++) { + v2[k] = v2[k+1]; + } + sizeV2--; + + // Update IDX: + idx = idx%sizeV2; + while(angle == v2[idx].first.first) { + idx = (idx+1)%sizeV2; + } + } +} diff --git a/aoc2019/P11.cpp b/aoc2019/P11.cpp new file mode 100644 index 0000000..fb75f6b --- /dev/null +++ b/aoc2019/P11.cpp @@ -0,0 +1,194 @@ +// Replace comma with space in input. +#define SIZE 50000000 +LL v[SIZE]; +int size = 0, relativeBase = 0, idx = 0, dir = 0; // 0 for up, 1 for right, 2 for down, 3 for left +PI pos(0,0); + +typedef map MAP; +MAP m; // true for white +bool willPaint = true; + +LL getInput() { + if(m.find(pos) == m.end()) { + cout << "Reading empty 0" << endl; + return 0; + } + cout << "Reading " << m[pos] << endl; + return m[pos]; +} + +void out(LL x) { + cout << "Writing " << x << endl; + if(willPaint) { + m[pos] = x; + cout << "Color " << x << " at " << pos.XX << ", " << pos.YY << endl; + } + else { + if(x == 0) { + dir = (dir+3)%4; // left + cout << "Turned left and walked to "; + } + else { + dir = (dir+1)%4; // right + cout << "Turned right and walked to "; + } + switch(dir) { + case 0: + pos.YY--; + break; + case 1: + pos.XX++; + break; + case 2: + pos.YY++; + break; + case 3: + pos.XX--; + break; + } + cout << pos.XX << "," << pos.YY << endl; + } + willPaint = !willPaint; +} + +int getIndex(vector &modes, int param) { + int mode = param-1 < modes.size() ? modes[param-1] : 0; + if(idx+param < 0 || idx+param >= SIZE) { + cerr << "PARAM RANGE " << idx << "+" << param << endl; + die(); + } + + if(mode == 1) { // 1 => immediate mode + return idx+param; + } + LL x = v[idx+param]; + if(mode == 2) { // 2 => relative mode + if(relativeBase + x < 0 || relativeBase+x >= SIZE) { + cerr << "RELATIVE PARAM RANGE " << relativeBase << "+" << x << endl; + die(); + } + return relativeBase + x; + } + else { // 0 => position mode + if(x < 0 || x >= SIZE) { + cerr << "POSITION PARAM RANGE " << x << " from " << idx << ", param " << param << endl; + die(); + } + return x; + } +} + +LL get(vector &modes, int param) { + return v[getIndex(modes, param)]; +} + +void put(vector &modes, int param, LL val) { + v[getIndex(modes, param)] = val; +} + +// replace , with space in input +int main() { + LL x; + FORI(SIZE) { + v[i] = 0; + } + while(cin >> x) { + v[size++] = x; + } + + m[PI(0,0)] = 1; // Part 2 only! + + while(true) { + int opcode = v[idx]%100; + int modeBits = v[idx]/100; + vector modes; + while(modeBits > 0) { + modes.push_back(modeBits % 10); + modeBits/=10; + } + + if(opcode == 1) { + LL val = get(modes, 1) + get(modes, 2); + put(modes, 3, val); + idx+=4; + } + else if(opcode == 2) { + LL val = get(modes, 1) * get(modes, 2); + put(modes, 3, val); + idx+=4; + } + else if(opcode == 3) { + put(modes, 1, getInput()); + idx+=2; + } + else if(opcode == 4) { + out(get(modes, 1)); + idx+=2; + } + else if(opcode == 5) { + LL check = get(modes, 1); + LL pointer = get(modes, 2); + if(check != 0) { + idx = pointer; + } + else { + idx += 3; + } + } + else if(opcode == 6) { + LL check = get(modes, 1); + if(check == 0) { + idx = get(modes, 2); + } + else { + idx += 3; + } + } + else if(opcode == 7) { + LL p1 = get(modes, 1); + LL p2 = get(modes, 2); + put(modes, 3, p1 < p2 ? 1 : 0); + idx+=4; + } + else if(opcode == 8) { + LL p1 = get(modes, 1); + LL p2 = get(modes, 2); + put(modes, 3, p1 == p2 ? 1 : 0); + idx+=4; + } + else if(opcode == 9) { + relativeBase += get(modes, 1); + idx+=2; + } + else if(opcode == 99) { + break; + } + else { + cerr << "Unknown opcode: " << opcode << endl; + die(); + } + } + + // Output: + cout << "Answer 1: " << m.size() << endl; + int miX = 9999999, miY = 9999999, maX = -9999999, maY = -9999999; + FORIT(MAP, m) { + int x = it->first.XX; + int y = it->first.YY; + miX = min(miX, x); + miY = min(miY, y); + maX = max(maX, x); + maY = max(maY, y); + } + for(int y = miY; y <= maY; y++) { + for(int x = miX; x <= maX; x++) { + if(m.find(PI(x,y)) == m.end()) { + cout << ' '; + } + else { + cout << (m[PI(x,y)] ? '#' : ' '); + } + } + cout << endl; + } +} diff --git a/aoc2019/P12.cpp b/aoc2019/P12.cpp new file mode 100644 index 0000000..d71f725 --- /dev/null +++ b/aoc2019/P12.cpp @@ -0,0 +1,125 @@ +// Remove all, but the numbers from input and add number of steps first. +LL gcd(LL a, LL b) { + LL c; + while(a != 0) { + c = a; + a = b%a; + b = c; + } + return b; +} + +LL lcm(LL a, LL b) { + LL g = gcd(a,b); + return a*b/g; +} + +typedef pair PL4; +typedef pair PL8; + +int main() { + GI(steps); + LL p[4][3], v[4][3]; + FORI(4) { + cin >> p[i][0] >> p[i][1] >> p[i][2]; + v[i][0] = v[i][1] = v[i][2] = 0; + } + + // Simulate: + map seen[3]; + + set matched[3]; + vector A1[3]; + vector A2[3]; + LL best = 999999999999999; + + LL SCAN = 1000000; + for(LL k = 0; k < SCAN; k++) { + FORI(3) { + PL8 hash(PL4(PLL(p[0][i],p[1][i]),PLL(p[2][i],p[3][i])),PL4(PLL(v[0][i],v[1][i]),PLL(v[2][i],v[3][i]))); + if(matched[i].find(hash) != matched[i].end()) { + continue; // Already matched. + } + + if(seen[i].find(hash) != seen[i].end()) { + LL start = seen[i][hash]; + LL loopLength = k-start; + + // Check if better start with loopLength already is found: + bool skip = false; + for(int a = 0; a < (int)A2[i].size(); a++) { + if(A2[i][a] != loopLength) + continue; + if(A1[i][a] < start) { + skip = true; + break; + } + } + if(skip) { + seen[i].erase(hash); + continue; + } + + // Check if better LCM exists! + LL a1[3], a2[3]; + a1[0] = start; + a2[0] = loopLength; + for(int a = 0; a < (int)A1[(i+1)%3].size(); a++) { + a1[1] = A1[(i+1)%3][a]; + a2[1] = A2[(i+1)%3][a]; + for(int b = 0; b < (int)A1[(i+2)%3].size(); b++) { + a1[2] = A1[(i+2)%3][b]; + a2[2] = A2[(i+2)%3][b]; + + LL maxStart = max(max(a1[0],a1[1]),a1[2]); + // Find Least Common Multiple of the cycle lengths: + LL LCM = lcm(lcm(a2[0],a2[1]),a2[2]); + LL x = LCM + maxStart; + if(x < best) { + best = x; + } + } // b + } // a + + A1[i].push_back(start); + A2[i].push_back(loopLength); + matched[i].insert(hash); + seen[i].erase(hash); + } + else { // hash not in seen[i] + seen[i][hash] = k; + } + } // FORI 3 + + // Update velocities: + FORI(4) { + FORJ(4) { + if(i == j) + continue; + FORX(3) { + v[i][x] += p[j][x] > p[i][x] ? 1 : (p[j][x] < p[i][x] ? -1 : 0); + } + } + } + // Update positions: + FORI(4) { + FORX(3) { + p[i][x] += v[i][x]; + } + } + + if(k+1 == steps) { + LL answer1 = 0; + FORI(4) { + LL pot = 0, kin = 0; + FORX(3) { + pot += abs(p[i][x]); + kin += abs(v[i][x]); + } + answer1 += pot*kin; + } + cout << "Answer 1: " << answer1 << endl; + } + } + cout << "Answer 2: " << best << endl; +} diff --git a/aoc2019/run.sh b/aoc2019/run.sh new file mode 100755 index 0000000..fff7fb7 --- /dev/null +++ b/aoc2019/run.sh @@ -0,0 +1,37 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2019/top.cpp b/aoc2019/top.cpp new file mode 100644 index 0000000..41a5f17 --- /dev/null +++ b/aoc2019/top.cpp @@ -0,0 +1,73 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2020/P01.cpp b/aoc2020/P01.cpp new file mode 100644 index 0000000..64e424f --- /dev/null +++ b/aoc2020/P01.cpp @@ -0,0 +1,19 @@ +int main() { + vector v; + int x; + while(cin >> x) { + v.push_back(x); + } + for(int i = 0; i < (int)v.size()-1; i++) { + for(int j = i+1; j < (int)v.size(); j++) { + if(v[i]+v[j] == 2020) { + cout << "Answer 1: " << (v[i]*v[j]) << endl; + } + for(int k = j+1; k < (int)v.size(); k++) { + if(v[i]+v[j]+v[k] == 2020) { + cout << "Answer 2: " << (v[i]*v[j]*v[k]) << endl; + } + } + } + } +} diff --git a/aoc2020/P02.cpp b/aoc2020/P02.cpp new file mode 100644 index 0000000..2c1997f --- /dev/null +++ b/aoc2020/P02.cpp @@ -0,0 +1,22 @@ +// Remove - and : from input +int main() { + int answer1 = 0, answer2 = 0, mi, ma; + char c; string s; + while(cin >> mi >> ma >> c >> s) { + int cnt = 0; + FORUI(s.size()) { + if(s[i] == c) { + cnt++; + } + } + if(mi <= cnt && cnt <= ma) { + answer1++; + } + char c1 = s[mi-1], c2 = s[ma-1]; + if(c1 == c && c2 != c || c1 != c && c2 == c) { + answer2++; + } + } + cout << "Answer 1: " << answer1 << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2020/P03.cpp b/aoc2020/P03.cpp new file mode 100644 index 0000000..87c99db --- /dev/null +++ b/aoc2020/P03.cpp @@ -0,0 +1,31 @@ +int main() { + vector v; + string s; + while(cin >> s) { + v.push_back(s); + } + LL answer = 1; + vector slopes; // Part 2 + slopes.push_back(PI(1,1)); + slopes.push_back(PI(3,1)); // For part 1, only have this + slopes.push_back(PI(5,1)); + slopes.push_back(PI(7,1)); + slopes.push_back(PI(1,2)); + + FORIT(vector, slopes) { + int dx = it->first; + int dy = it->second; + + PI p(0,0); + int trees = 0; + while(p.YY < v.size()) { + if(v[p.YY][p.XX % v[0].size()] == '#') { + trees++; + } + p.XX+=dx; + p.YY+=dy; + } + answer*=trees; + } + cout << "Answer: " << answer << endl; +} diff --git a/aoc2020/P04.cpp b/aoc2020/P04.cpp new file mode 100644 index 0000000..a926193 --- /dev/null +++ b/aoc2020/P04.cpp @@ -0,0 +1,143 @@ +typedef map MAP; + +string fields[8] = {"byr","iyr","eyr","hgt","hcl","ecl","pid","cid"}; +MAP m; +set eyes; + +bool isInt(string &s) { + FORUI(s.size()) { + char c = s[i]; + if(!(c >= '0' && c <= '9')) { + return false; + } + } + return true; +} + +bool isHex(char c) { + return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f'); +} + +bool inRange(int low, int high, string &s) { + if(!isInt(s)) + return false; + int y = stoi(s); + return low <= y && y <= high; +} + +bool endsWith(string &s, string end) { + if(end.size() > s.size()) + return false; + return equal(end.rbegin(), end.rend(), s.rbegin()); +} + +bool check() { + FORI(8) { + string k = fields[i]; + if(m.find(k) == m.end()) { + if(k == "cid") { + continue; + } + else { + cout << "FAIL MISSING " << k << endl; + return false; + } + } + string v = m[k]; + if(k == "byr") { + if(!inRange(1920, 2002, v)) { + cout << "FAIL byr " << v << endl; + return false; + } + } + else if(k == "iyr") { + if(!inRange(2010, 2020, v)) { + cout << "FAIL iyr " << v << endl; + return false; + } + } + else if(k == "eyr") { + if(!inRange(2020, 2030, v)) { + cout << "FAIL eyr " << v << endl; + return false; + } + } + else if(k == "hgt") { + if(endsWith(v, "cm")) { + v = v.substr(0, v.size()-2); + if(!inRange(150, 193, v)) { + cout << "FAIL Height in cm: " << v << endl; + return false; + } + } + else if(endsWith(v, "in")) { + v = v.substr(0, v.size()-2); + if(!inRange(59, 76, v)) { + cout << "FAIL Height in in: " << v << endl; + return false; + } + } + else + return false; + } + else if(k == "hcl") { + if(v[0] != '#' || v.size() != 7) { + cout << "FAIL hcl missing #: " << v << endl; + return false; + } + FORJ(6) { + if(!isHex(v[j+1])) { + cout << "FAIL hcl hex: " << v << endl; + return false; + } + } + } + else if(k == "ecl") { + if(eyes.find(v) == eyes.end()) { + cout << "FAIL unknown eye color: " << v << endl; + return false; + } + } + else if(k == "pid") { + if(v.size() != 9 || !isInt(v)) { + cout << "FAIL pid: " << v << endl; + return false; + } + } + } + return true; +} + +// Remove : from input +int main() { + int answer = 0; + + eyes.insert("amb"); + eyes.insert("blu"); + eyes.insert("brn"); + eyes.insert("gry"); + eyes.insert("grn"); + eyes.insert("hzl"); + eyes.insert("oth"); + + string line, k, v; + while(true) { + bool hasLine = getline(cin, line); + if(!hasLine || line == "") { + if(check()) + answer++; + m.clear(); + } + if(!hasLine) { + cout << answer << endl; + return 0; + } + if(line == "") { + continue; + } + stringstream ss; ss << line; + while(ss >> k >> v) { + m[k] = v; + } + } // while true +} diff --git a/aoc2020/P05.cpp b/aoc2020/P05.cpp new file mode 100644 index 0000000..ecf7c8f --- /dev/null +++ b/aoc2020/P05.cpp @@ -0,0 +1,36 @@ +int main() { + int answer1 = 0; + string s; + set seats; + while(cin >> s) { + int miX = 0, maX = 127, miY = 0, maY = 7; + FORUI(s.size()) { + char c = s[i]; + if(c == 'B') { + miX = (maX+miX)/2; + } + else if(c == 'F') { + maX = (maX+miX)/2; + } + else if(c == 'R') { + miY = (maY+miY)/2; + } + else if(c == 'L') { + maY = (maY+miY)/2; + } + } + int id = 8*maX + maY; + seats.insert(id); + answer1 = max(answer1, id); + cout << "X: " << miX << "," << maX << ", Y: " << miY << "," << maY << ", ID: " << id << endl; + } + cout << "Answer 1: " << answer1 << endl; + int last = -1; + FORIT(set, seats) { + int id = *it; + int space = *it - last; + if(last != -1 && space != 1) + cout << "Seat ID " << id << " Space: " << space << ", so answer 2 can be: " << id-1 << endl; + last = id; + } +} diff --git a/aoc2020/P06.cpp b/aoc2020/P06.cpp new file mode 100644 index 0000000..878d26e --- /dev/null +++ b/aoc2020/P06.cpp @@ -0,0 +1,43 @@ +int main() { + int answer1 = 0, answer2 = 0; bool firstPerson = true; + set S, intersection; string s; + while(true) { + bool hasLine = getline(cin, s); + if(!hasLine || s == "") { + answer1 += S.size(); + S.clear(); + firstPerson = true; + cout << "Adding " << intersection.size() << endl; + answer2 += intersection.size(); + intersection.clear(); + } + if(!hasLine) + break; + if(s == "") + continue; + // Part 1: + FORUI(s.size()) { + S.insert(s[i]); + } + // Part 2: + if(firstPerson) { // Take all: + FORUI(s.size()) { + intersection.insert(s[i]); + } + firstPerson = false; + cout << "First person => " << intersection.size() << endl; + } + else { // Intersect: + set T; + FORUI(s.size()) { + if(intersection.find(s[i]) != intersection.end()) { + T.insert(s[i]); + } + } + cout << "Size intersection: " << intersection.size() << " from " << T.size() << endl; + intersection = T; + } + } + cout << answer1 << endl; + cout << answer2 << endl; +} diff --git a/aoc2020/P07.cpp b/aoc2020/P07.cpp new file mode 100644 index 0000000..90b5b29 --- /dev/null +++ b/aoc2020/P07.cpp @@ -0,0 +1,101 @@ +/* +Cleanup input: +"bags contain" -> "bag" + */ +map* > m; +typedef map MAP; + +struct Bag { + MAP content; + LL size; +}; +map bags; + +bool isBag(string &s) { + if(s.size() < 3) + return false; + return s[0] == 'b' && s[1] == 'a' && s[2] == 'g'; +} + +string getBagColor(stringstream &ss) { + stringstream out; + string s; + bool first = true; + while(ss >> s) { + if(isBag(s)) { + // Ensure bag exists: + string ret = out.str(); + if(bags.find(ret) == bags.end()) { + Bag *b2 = new Bag; + b2->size = -1; + bags[ret] = b2; + } + + return ret; + } + if(first) { + out << s; + first = false; + } + else { + out << " " << s; + } + } + return NULL; +} + +LL getSize(string s) { + Bag &b = *bags[s]; + if(b.size >= 0) + return b.size; + LL ret = 1; + FORIT(MAP, b.content) { + ret += it->second * getSize(it->first); + } + b.size = ret; + cout << "Size of " << s << ": " << ret << endl; + return ret; +} + +int main() { + + string s; + while(getline(cin, s)) { + stringstream ss1, ss2; + ss1 << s; + string b1 = getBagColor(ss1); + int amount; + while(ss1 >> amount) { + string b2 = getBagColor(ss1); + set *S = new set; + if(m.find(b2) == m.end()) { + m[b2] = S; + } + bags[b1]->content[b2] = amount; + cout << b1 << " contains " << amount << " x " << b2 << endl; + m[b2]->insert(b1); + } + } + + set above; + stack ready; + ready.push("shiny gold"); + above.insert("shiny gold"); + + while(!ready.empty()) { + string t2 = ready.top(); + ready.pop(); + if(m.find(t2) == m.end()) + continue; // Not in m! + set &S2 = *m[t2]; + FORIT(set, S2) { + s = *it; + if(above.find(s) == above.end()) { + ready.push(s); + } + above.insert(s); + } + } + cout << "Answer 1: " << (int)above.size()-1 << endl; + cout << "Answer 2: " << getSize("shiny gold")-1 << endl; +} diff --git a/aoc2020/P08.cpp b/aoc2020/P08.cpp new file mode 100644 index 0000000..8256c40 --- /dev/null +++ b/aoc2020/P08.cpp @@ -0,0 +1,62 @@ +int acc; +vector v; + +bool halts() { + int idx = 0; + acc = 0; + set seen; + + while(idx < (int)v.size()) { + if(seen.find(idx) != seen.end()) { + return false; + } + seen.insert(idx); + string op = v[idx].first; + int val = v[idx].second; + if(op == "nop") { + idx++; + } + else if(op == "acc") { + acc += val; + idx++; + } + else if(op == "jmp") { + idx += val; + } + } + return true; +} + +int main() { + string op; + int val; + while(cin >> op >> val) { + v.push_back(PSI(op,val)); + } + + // For part run, just run halts and output acc. + halts(); + cout << "Answer 1: " << acc << endl; + + // Part 2: + FORUI(v.size()) { + if(v[i].first == "acc") + continue; // acc is ok + if(v[i].first == "nop") { + v[i].first = "jmp"; + if(halts()) { + cout << "Answer 2: " << acc << endl; + return 0; + } + v[i].first = "nop"; + } + else { // is jmp + v[i].first = "nop"; + if(halts()) { + cout << "Answer 2: " << acc << endl; + return 0; + } + v[i].first = "jmp"; + } + } +} diff --git a/aoc2020/P09.cpp b/aoc2020/P09.cpp new file mode 100644 index 0000000..2decf96 --- /dev/null +++ b/aoc2020/P09.cpp @@ -0,0 +1,56 @@ +// Add pre-append to input +int main() { + GI(pSize); + vector all; + + // Read preample: + LL preample[25], x; + int idx = 0; + FORI(pSize) { + cin >> preample[idx++]; + all.push_back(preample[idx-1]); + } + // Find first problematic char: + LL invalid; + while(cin >> x) { + all.push_back(x); + bool match = false; + for(int i = 0; !match && i+1 < pSize; i++) { + for(int j = i+1; j < pSize; j++) { + if(preample[i] + preample[j] == x) { + match = true; + break; + } + } + } + if(!match) { + cout << "Answer 1: " << x << endl; + invalid = x; + break; + } + preample[idx++ % pSize] = x; + } + while(cin >> x) { + all.push_back(x); + } + + // Part 2: + for(int i = 0; i < (int)all.size()-1; i++) { + LL sum = all[i]; + for(int j = i+1; j < (int)all.size(); j++) { + sum+=all[j]; + if(sum > invalid) + break; // could not be found + if(sum == invalid) { + // Find min and max in range: + LL mi = all[i], ma = all[i]; + for(int k = i+1; k <= j; k++) { + mi = min(mi, all[k]); + ma = max(ma, all[k]); + } + cout << "Answer 2: " << mi+ma << endl; + return 0; + } + } + } +} diff --git a/aoc2020/P10.cpp b/aoc2020/P10.cpp new file mode 100644 index 0000000..7a6e6cf --- /dev/null +++ b/aoc2020/P10.cpp @@ -0,0 +1,35 @@ +int main() { + vector v; + LL x; + while(cin >> x) { + v.push_back(x); + } + cout << "Read " << v.size() << " adaptors" << endl; + + v.push_back(0); // outlet + sort(v.begin(), v.end()); + v.push_back(*v.rbegin() + 3); + + int cnt1 = 0, cnt3 = 0; + for(int i = 1; i < (int)v.size(); i++) { + int diff = v[i]-v[i-1]; + if(diff == 1) + cnt1++; + else if(diff == 3) + cnt3++; + } + cout << "Answer 1: " << cnt1*cnt3 << endl; + + // Part 2: + LL *ret = new LL[v.size()]; + ret[0] = 1; + for(int i = 1; i < (int)v.size(); i++) { + ret[i] = 0; + for(int j = i-1; j >= 0; j--) { + if(v[j]+3 < v[i]) + break; + ret[i] += ret[j]; + } + } + cout << "Answer 2: " << ret[v.size()-1] << endl; +} diff --git a/aoc2020/P11.cpp b/aoc2020/P11.cpp new file mode 100644 index 0000000..4639d6a --- /dev/null +++ b/aoc2020/P11.cpp @@ -0,0 +1,96 @@ +#define SIZE 200 + +string m1[SIZE], m2[SIZE]; +int width, height = 0; +PI dirs[8] = {PI(-1,0),PI(-1,-1),PI(-1,1),PI(0,1),PI(0,-1),PI(1,-1),PI(1,0),PI(1,1)}; + +void print() { + FORY(height) { + cout << m1[y] << endl; + } + cout << endl; +} + +bool same() { + FORY(height) { + FORX(width) { + if(m1[y][x] != m2[y][x]) + return false; + } + } + return true; +} + +int main() { + while(getline(cin, m1[height])) { + m2[height] = m1[height]; + height++; + } + width = (int)m1[0].size(); + // Simulate: + print(); + int rounds = 0; + do { + FORY(height) { + FORX(width) { + char c = m1[y][x]; + m2[y][x] = c; + if(c == 'L') { + // Find out if it gets occupied: + bool allEmpty = true; + FORI(8) { // Dirs + for(int j = 1; true; j++) { // Only part 2! + int xx = x + dirs[i].XX*j; + int yy = y + dirs[i].YY*j; + if(xx < 0 || xx >= width || yy < 0 || yy >= height) + break; + if(m1[yy][xx] == '#') { + allEmpty = false; + break; + } + if(m1[yy][xx] == 'L') { + break; + } + } + } + if(allEmpty) { + m2[y][x] = '#'; // Occupied now. + } + } + else if(c == '#') { + // Find out if it gets occupied: + int cntOccupied = 0; + FORI(8) { // Dirs + for(int j = 1; true; j++) { // Only part 2! + int xx = x + dirs[i].XX*j; + int yy = y + dirs[i].YY*j; + if(xx < 0 || xx >= width || yy < 0 || yy >= height) + break; + if(m1[yy][xx] == '#') { + cntOccupied++; + break; + } + if(m1[yy][xx] == 'L') { + break; + } + } + } + if(cntOccupied >= 5) // 4 for part 1 + m2[y][x] = 'L'; // Leave + } + } + } + rounds++; + swap(m1, m2); + print(); + }while(!same()); + + int answer1 = 0; + FORY(height) { + FORX(width) { + if(m1[y][x] == '#') + answer1++; + } + } + cout << answer1 << endl; +} diff --git a/aoc2020/P12.cpp b/aoc2020/P12.cpp new file mode 100644 index 0000000..b61f4f8 --- /dev/null +++ b/aoc2020/P12.cpp @@ -0,0 +1,85 @@ +int main() { + string s; + int x = 0, y = 0, dir = 1; // 0 North, 1 East, 2 South, 3 West. + int vx = 10, vy = -1; + while(cin >> s) { + char c = s[0]; + int v = 0; + for(int i = 1; i < (int)s.size(); i++) { + v = 10*v + s[i]-'0'; + } + // Simulate: + switch(c) { + case 'N': + vy-=v; + break; + case 'S': + vy+=v; + break; + case 'E': + vx+=v; + break; + case 'W': + vx-=v; + break; + case 'L': + for(int i = 0; i < v; i+=90) { + swap(vx,vy); + vy = -vy; + } + break; + case 'R': + for(int i = 0; i < v; i+=90) { + swap(vx,vy); + vx = -vx; + } + break; + case 'F': + x += v * vx; + y += v * vy; + break; + } + cout << "Moved " << c << " " << v << " to " << x << ", " << y << ", waypoint " << vx << ", "<< vy </dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2020/top.cpp b/aoc2020/top.cpp new file mode 100644 index 0000000..41a5f17 --- /dev/null +++ b/aoc2020/top.cpp @@ -0,0 +1,73 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2021/P01.cpp b/aoc2021/P01.cpp new file mode 100644 index 0000000..485b04b --- /dev/null +++ b/aoc2021/P01.cpp @@ -0,0 +1,13 @@ +int main() { + int size = 0, v[2010]; + while(cin >> v[size++]) + ; + int answer = 0; + for(int i = 3; i < size; i++) { + if(v[i] > v[i-3]) { + cout << "Larger at " << i << ": " << v[i] << endl; + answer++; + } + } + cout << answer << endl; +} diff --git a/aoc2021/P02.cpp b/aoc2021/P02.cpp new file mode 100644 index 0000000..5ce1493 --- /dev/null +++ b/aoc2021/P02.cpp @@ -0,0 +1,20 @@ +int main() { + PLL p(0,0), p2(0,0); string s; LL x, aim = 0; + while(cin >> s >> x) { + if(s[0] == 'f') { + p.XX+=x; + p2.XX+=x; + p2.YY+=aim*x; + } + else if(s[0] == 'd') { + p.YY+=x; + aim+=x; + } + else { + p.YY-=x; + aim-=x; + } + } + cout << p.XX*p.YY << endl; + cout << p2.XX*p2.YY << endl; +} diff --git a/aoc2021/P03.cpp b/aoc2021/P03.cpp new file mode 100644 index 0000000..08b1626 --- /dev/null +++ b/aoc2021/P03.cpp @@ -0,0 +1,95 @@ +int btod(string s) { + int ret = 0; + FORUI(s.size()) { + ret <<= 1; + if(s[i] == '1') + ret+=1; + } + return ret; +} + +int main() { + ULL gamma = 0, epsilon = 0; + int cnt0[100], cnt1[100]; + FORI(100) + cnt0[i] = cnt1[i] = 0; + vector o2, co2; + string s; + int size; + while(cin >> s) { + size = (int)s.size(); + o2.push_back(s); + co2.push_back(s); + FORI(size) { + if(s[i] == '0') + cnt0[i]++; + else + cnt1[i]++; + } + } + FORI(size) { + gamma<<=1; + epsilon<<=1; + if(cnt0[i] > cnt1[i]) { + epsilon++; + } + else { + gamma++; + } + } + cout << "epsilon: " << epsilon << ", gamma: " << gamma << ", answer 1: " << (gamma*epsilon) << endl; + // Part 2: + int numCO2, numO2; + + FORI(size) { + vector o, c; + + int c0 = 0, c1 = 0; + FORIT(vector, o2) { + if((*it)[i] == '1') + c1++; + else + c0++; + } + + FORIT(vector, o2) { + char keep = c1 >= c0 ? '1' : '0'; + if((*it)[i] == keep) + o.push_back(*it); + } + o2 = o; + cout << "After " << i << ": " << o2.size() << " o2 left:" << endl; + FORIT(vector, o2) { + cout << " " << *it << ": " << btod(*it) << endl; + } + if(o2.size() == 1) { + numO2 = btod(o2[0]); + cout << "Count O2 set: " << numO2 << endl; + } + + + c0 = 0, c1 = 0; + FORIT(vector, co2) { + if((*it)[i] == '1') + c1++; + else + c0++; + } + + FORIT(vector, co2) { + char keep = c0 <= c1 ? '0' : '1'; + if((*it)[i] == keep) + c.push_back(*it); + } + co2 = c; + /*cout << "After " << i << ": " << co2.size() << " co2 left" << endl; + FORIT(vector, co2) { + cout << " " << *it << ": " << btod(*it) << endl; + }*/ + if(co2.size() == 1) { + numCO2 = btod(co2[0]); + //cout << "Count CO2 set: " << numCO2 << endl; + } + } + cout << "Answer 2: " << (numO2*numCO2) << endl; +} diff --git a/aoc2021/P04.cpp b/aoc2021/P04.cpp new file mode 100644 index 0000000..6136963 --- /dev/null +++ b/aoc2021/P04.cpp @@ -0,0 +1,89 @@ +struct Board { + int b[5][5]; + + int bingo(int X) { + FORY(5) { + FORX(5) { + if(b[y][x] == X) { + b[y][x] = -b[y][x]-1; + } + } + } + // Check: + bool won = false; + FORY(5) { + bool ok = true; + FORX(5) { + if(b[y][x] >= 0) { + ok = false; + break; + } + } + if(ok) + won = true; + } + FORX(5) { + bool ok = true; + FORY(5) { + if(b[y][x] >= 0) { + ok = false; + break; + } + } + if(ok) + won = true; + } + if(!won) + return -1; + int ret = 0; + FORY(5) { + FORX(5) { + if(b[y][x] >= 0) { + ret += b[y][x]; + } + } + } + return ret * X; + } +}; + +int main() { + vector v; + int x; string s; + { + getline(cin, s); + stringstream ss; ss << s; + while(ss >> x) { + v.push_back(x); + } + } + // Read boards: + Board boards[1000]; + int size = 0; + while(getline(cin, s)) { + Board &b = boards[size++]; + FORY(5) { + getline(cin, s); + stringstream ss; ss << s; + FORX(5) { + ss >> b.b[y][x]; + } + } + } + // Simulate: + bool *won = new bool[size]; + FORI(size) + won[i] = false; + FORUI(v.size()) { + int x = v[i]; + FORJ(size) { + if(won[j]) + continue; // Already won. + int v = boards[j].bingo(x); + if(v >= 0) { + cout << "Board " << j << " wins with: " << v << endl; + won[j] = true; + } + } + } +} diff --git a/aoc2021/P05.cpp b/aoc2021/P05.cpp new file mode 100644 index 0000000..64650fb --- /dev/null +++ b/aoc2021/P05.cpp @@ -0,0 +1,51 @@ +// Replace , with space in input +typedef pair Line; +int main() { + vector lines; + int a, b, c, d, miX=99999,miY=99999,maX=-99999,maY=-999999; + string s; + while(cin >> a >> b >> s >> c >> d) { + lines.push_back(Line(PI(a,b), PI(c,d))); + miX = min(miX, min(a,c)); + miY = min(miY, min(b,d)); + maX = max(maX, max(a,c)); + maY = max(maY, max(b,d)); + } + cout << lines.size() << " lines read. Max: " << maX << ", " << maY << endl; + int Q[1000][1000]; + FORI(1000){ + FORJ(1000) { + Q[j][i] = 0; + } + } + FORIT(vector, lines) { + int x1 = it->XX.XX, x2 = it->YY.XX, y1 = it->XX.YY, y2 = it->YY.YY; + if(x1 == x2) { + for(int y = min(y1,y2); y <= max(y1,y2); y++) { + Q[y][x1]++; + } + } + else if(y1 == y2) { + for(int x = min(x1,x2); x <= max(x1,x2); x++) { + Q[y1][x]++; + } + } + else { + int dx = x2 > x1 ? 1 : -1; + int dy = y2 > y1 ? 1 : -1; + for(int x = x1, y = y1; true; x+=dx, y+=dy) { + Q[y][x]++; // Only part 2 + if(x == x2) + break; + } + } + } + int answer1 = 0; + FORI(1000){ + FORJ(1000) { + if(Q[j][i] > 1) + answer1++; + } + } + cout << answer1 << endl; +} diff --git a/aoc2021/P06.cpp b/aoc2021/P06.cpp new file mode 100644 index 0000000..62b5a93 --- /dev/null +++ b/aoc2021/P06.cpp @@ -0,0 +1,20 @@ +int main() { + ULL v[9]; FORI(9) v[i] = 0; + int x; + while(cin >> x) { + v[x]++; + } + FORI(256) { // Simulate 80 days in part 1 + LL zeros = v[0]; + for(int j = 0; j < 9; j++) { + v[j-1] = v[j]; + } + // Add for zeros: + v[6]+= zeros; + v[8] = zeros; + } + LL sum = 0; + FORI(9) + sum += v[i]; + cout << sum << endl; +} diff --git a/aoc2021/P07.cpp b/aoc2021/P07.cpp new file mode 100644 index 0000000..01b112c --- /dev/null +++ b/aoc2021/P07.cpp @@ -0,0 +1,52 @@ +vector v; + +int getCost(int destination) { + int ret = 0; + FORIT(vector, v) { + ret += abs(*it-destination); + } + return ret; +} + +LL getCost2(int destination) { + LL ret = 0; + FORIT(vector, v) { + LL dist = abs(*it-destination); + ret += (dist+1)*dist/2; + } + return ret; +} + +int main() { + int x; + while(cin >> x) { + v.push_back(x); + } + sort(v.begin(), v.end()); + + int bestCost = getCost(v[0]); // Cost is now the price of all to the right + 0 for the left-most + cout << "Initial cost at " << v[0] << ": " << bestCost << endl; + int cost = bestCost; + int below = 0, above = (int)v.size()-1; + for(int i = 1; i < (int)v.size(); i++) { + int dist = v[i]-v[i-1]; + below++; + cost -= dist*above; + above--; + cost += dist*below; + bestCost = min(bestCost, cost); + /*if(cost != getCost(v[i])) { + cerr << "Error! Cost should be " << getCost(v[i]) << endl; + return 1; + }//*/ + cout << "Cost at " << i << " / " << v[i] << ": " << cost << endl; + } + cout << "Answer 1: " << bestCost << endl; + + LL bestCost2 = 99999999; + for(int i = v[0]; i <= v[v.size()-1]; i++) { + LL cost2 = getCost2(i); + bestCost2 = min(bestCost2, cost2); + } + cout << "Answer 2: " << bestCost2 << endl; +} diff --git a/aoc2021/P08.cpp b/aoc2021/P08.cpp new file mode 100644 index 0000000..3ccaffd --- /dev/null +++ b/aoc2021/P08.cpp @@ -0,0 +1,144 @@ +string anotb(const string &a, const string &b) { + set s; + FORUI(b.size()) { + char c = b[i]; + s.insert(c); + } + + stringstream ss; + FORUI(a.size()) { + char c= a[i]; + if(s.find(c) == s.end()) { + ss << c; + } + } + return ss.str(); +} +string aandb(const string &a, const string &b) { + set s; + FORUI(b.size()) { + char c = b[i]; + s.insert(c); + } + stringstream ss; + FORUI(a.size()) { + char c= a[i]; + if(s.find(c) != s.end()) { + ss << c; + } + } + return ss.str(); +} + +bool cmp(const string &a, const string &b) { + if(a.size() != b.size()) + return a.size() < b.size(); + return a < b; +} + +int main() { + string line, s; + int cnt[10], answer2 = 0; + FORI(10) + cnt[i] = 0; + while(getline(cin, line)) { + vector v, q; + stringstream ss; ss << line; + FORI(10) { + ss >> s; + sort(&s[0], &s[s.size()]); + v.push_back(s); + } + ss >> s; if(s != "|") die(); // assert | + + // 4 to guess: + FORI(4) { + ss >> s; + sort(&s[0], &s[s.size()]); + q.push_back(s); + if(s.size() == 2) + cnt[1]++; + else if(s.size() == 3) + cnt[7]++; + else if(s.size() == 4) + cnt[4]++; + else if(s.size() == 7) + cnt[8]++; + } + + // Part 2 analysis: + sort(v.begin(), v.end(), cmp); + string s0; + const string s069[3] = {v[6], v[7], v[8]}; + const string s1 = v[0]; + string s2; + string s3; + const string s235[3] = {v[3], v[4], v[5]}; + const string s4 = v[2]; + string s5; + string s6; + const string s7 = v[1]; + const string s8 = v[9]; + string s9; + + // Find some segments a-g: + string bd = anotb(s4,s1); + // Find d and s0: + FORI(3) { + s0 = s069[i]; + string d = anotb(bd, s0); + if(d.size() == 1) { + break; // Found s0 + } + } + // Find c, s9, and s6: + FORI(3) { + string x = s069[i]; + if(x == s0) { + continue; // Not a match + } + string y = anotb(s1, x); + if(y.size() == 1) { + s6 = x; + } + else { + s9 = x; + } + } + // Find s2, s3, and s5: + FORI(3) { + string x = s235[i]; + string y = aandb(s1, x); + string z = anotb(s6, x); + if(y.size() == 2) { + s3 = x; + } + else if(z.size() == 1) { + s5 = x; + } + else { + s2 = x; + } + } + + // Use map: + map m; + m[s0] = 0; + m[s1] = 1; + m[s2] = 2; + m[s3] = 3; + m[s4] = 4; + m[s5] = 5; + m[s6] = 6; + m[s7] = 7; + m[s8] = 8; + m[s9] = 9; + int c4 = 0; + FORIT(vector, q) { + c4 = 10*c4 + m[*it]; + } + answer2 += c4; + } + cout << "Answer 1: " << (cnt[1]+cnt[8]+cnt[4]+cnt[7]) << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2021/P09.cpp b/aoc2021/P09.cpp new file mode 100644 index 0000000..ff9de9a --- /dev/null +++ b/aoc2021/P09.cpp @@ -0,0 +1,68 @@ +int main() { + string v[102], s; + int height = 0, width; + while(cin >> s) { + v[height] = s; + height++; + } + width = (int)v[0].size(); + cout << "Read map " << width << " x " << height << endl; + PI neighbours[4] = {PI(-1,0), PI(1,0), PI(0,1), PI(0,-1)}; + + int answer1 = 0; + vector basins; + set allBasins; + + FORY(height) { + FORX(width) { + char h = v[y][x]; + bool allHigher = true; + FORI(4) { + const PI &p = neighbours[i]; + int xx = x+p.XX; + int yy = y+p.YY; + if(xx >= 0 && yy >= 0 && xx < width && yy < height) { + if(v[yy][xx] <= h) { + allHigher = false; + break; + } + } + } + if(allHigher) { + cout << "LOW " << x << ", " << y << endl; + answer1 += h+1-'0'; + + if(allBasins.find(PI(x,y)) != allBasins.end()) + continue; // Already seen basin. + + // Compute basin: + stack ready; + set basin; + ready.push(PI(x,y)); + while(!ready.empty()) { + PI p = ready.top(); ready.pop(); + if(basin.find(p) != basin.end()) + continue; // Already seen + basin.insert(p); + allBasins.insert(p); + FORI(4) { + const PI &q = neighbours[i]; + int xx = p.XX+q.XX; + int yy = p.YY+q.YY; + if(xx >= 0 && yy >= 0 && xx < width && yy < height) { + if(v[yy][xx] != '9') { + ready.push(PI(xx,yy)); + } + } + } + } + cout << "Basin of size " << basin.size() << endl; + basins.push_back(basin.size()); + } + } // FORX width + } // FORY height + sort(basins.begin(), basins.end()); + LL answer2 = basins[basins.size()-1] * basins[basins.size()-2] * basins[basins.size()-3]; + cout << answer1 << endl; + cout << answer2 << endl; +} diff --git a/aoc2021/P10.cpp b/aoc2021/P10.cpp new file mode 100644 index 0000000..3ae91fa --- /dev/null +++ b/aoc2021/P10.cpp @@ -0,0 +1,65 @@ +int main() { + map scores; + scores[')'] = 3; + scores[']'] = 57; + scores['}'] = 1197; + scores['>'] = 25137; + map match; + match['{'] = '}'; + match['}'] = '{'; + match['('] = ')'; + match[')'] = '('; + match['<'] = '>'; + match['>'] = '<'; + match['['] = ']'; + match[']'] = '['; + vector v; + map p2; + p2[')'] = 1; + p2[']'] = 2; + p2['}'] = 3; + p2['>'] = 4; + + string line; + LL answer1 = 0; + while(getline(cin, line)) { + stack s; + bool error = false; + FORI(line.size()) { + char c = line[i], top; + switch(c) { + case '[': + case '(': + case '<': + case '{': + s.push(c); + break; + default: + top = s.top(); s.pop(); + if(match[top] != c) { + cout << line << " - Expected " << match[top] << ", but found " << c << " instead." << endl; + answer1 += scores[c]; + error = true; + } + break; + } + if(error) + break; + } + if(error) + continue; + // Part 2: + cout << line << " - Complete by adding "; + LL score = 0; + while(!s.empty()) { + score = 5*score + p2[match[s.top()]]; + cout << match[s.top()]; + s.pop(); + } + cout << ": " << score << endl; + v.push_back(score); + } + sort(v.begin(), v.end()); + cout << answer1 << endl; + cout << v[v.size()/2] << endl; +} diff --git a/aoc2021/P11.cpp b/aoc2021/P11.cpp new file mode 100644 index 0000000..3cc2a63 --- /dev/null +++ b/aoc2021/P11.cpp @@ -0,0 +1,80 @@ +int Q[12][12]; // +1, so we don't have to worry about corners + +void print() { + FORY(10) { + FORX(10) { + int q = Q[y+1][x+1]; + if(q == -1) + cout << "*"; + else if(q > 9) + cout << (char)('a'+q-10); + else + cout << q; + } + cout << endl; + } + cout << endl; +} + +int main() { + LL flashes = 0; + string s; + FORY(10) { + cin >> s; + FORX(10) { + Q[y+1][x+1] = s[x]-'0'; + } + } + cout << "Input:" << endl; + print(); + + FORI(1000) { + // First increase: + FORY(10) { + FORX(10) { + Q[y+1][x+1]++; + } + } + + // Flash: + bool any = true; + int f2 = 0; + while(any) { + any = false; + FORY(10) { + FORX(10) { + int q = Q[y+1][x+1]; + if(q == -1) + continue; // Already flashed + if(q >= 10) { + any = true; + f2++; + flashes++; + Q[y+1][x+1] = -1; + for(int yy = y-1; yy <= y+1; yy++) { + for(int xx = x-1; xx <= x+1; xx++) { + if(Q[yy+1][xx+1] != -1) + Q[yy+1][xx+1]++; + } + } + } + } // FORX + } // FORY + } // while any + //cout << "After step " << (i+1) << ":" << endl; + //print(); + FORY(10) { + FORX(10) { + if(Q[y+1][x+1] == -1) + Q[y+1][x+1] = 0; + } + } + if(f2 == 100) { + cout << "Answer 2: " << (i+1) << endl; + return 0; + } + if(i == 99) { + cout << "Answer 1: " << flashes << endl; + } + } // FORI +} diff --git a/aoc2021/P12.cpp b/aoc2021/P12.cpp new file mode 100644 index 0000000..e89e8a1 --- /dev/null +++ b/aoc2021/P12.cpp @@ -0,0 +1,59 @@ +bool used[100]; +int idStart, idEnd; +map ids; +set con[100]; + +LL numPaths(int from, bool twiceVisited) { + if(from == idEnd) { + return 1; + } + LL ret = 0; + FORIT(set, con[from]) { + string s = *it; + int id = ids[s]; + if(id == idStart) + continue; + + // See if we can visit: + bool twiceNow = twiceVisited; + if(used[id]) { + if(twiceNow) + continue; // Already in use + twiceNow = true; + } + + bool switched = false; + if(!used[id] && s[0] >= 'a' && s[0] <= 'z') { + used[id] = true; + switched = true; + } + + ret += numPaths(id, twiceNow); + + if(switched) + used[id] = false; + } + return ret; +} + +// Replace - with space in input +int main() { + FORI(100) used[i] = false; + string a, b; + while(cin >> a >> b) { + if(ids.find(a) == ids.end()) + ids[a] = (int)ids.size(); + if(ids.find(b) == ids.end()) + ids[b] = (int)ids.size(); + con[ids[a]].insert(b); + con[ids[b]].insert(a); + } + cout << "Read " << ids.size() << " caves" << endl; + + idStart = ids["start"]; + idEnd = ids["end"]; + used[idStart] = true; + + LL answer1 = numPaths(idStart, false); + cout << answer1 << endl; +} diff --git a/aoc2021/P13.cpp b/aoc2021/P13.cpp new file mode 100644 index 0000000..7c77136 --- /dev/null +++ b/aoc2021/P13.cpp @@ -0,0 +1,61 @@ +// Replace , and = with space in input. Add -1 -1 between sections +char Q[2000][2000]; +int width = 0, height = 0; + +int main() { + FORY(2000) { + FORX(2000) { + Q[y][x] = '.'; + } + } + int x, y; + while(cin >> x >> y) { + if(x == -1) + break; + Q[y][x] = '#'; + width = max(width, x+1); + height = max(height, y+1); + } + // Fold: + string s; char c; + while(cin >> s >> s >> c >> x) { + y = x; + if(c == 'x') { + if(x < width/2) { + cerr << "Fold more left!" << endl; + die(); + } + for(int xx = x+1; xx < width; xx++) { + for(int yy = 0; yy < height; yy++) { + if(Q[yy][xx] == '#') + Q[yy][x - (xx-x)] = '#'; + } + } + width = x; + } + else { // y + if(y < height/2) { + cerr << "Fold more up!" << endl; + die(); + } + for(int yy = y+1; yy < height; yy++) { + for(int xx = 0; xx < width; xx++) { + if(Q[yy][xx] == '#') + Q[y - (yy-y)][xx] = '#'; + } + } + height = y; + } + //break; // For Part 1 + } + int cnt = 0; + FORY(height) { + FORX(width) { + cout << Q[y][x]; + if(Q[y][x] == '#') + cnt++; + } + cout << endl; + } + cout << cnt << endl; +} diff --git a/aoc2021/P14.cpp b/aoc2021/P14.cpp new file mode 100644 index 0000000..80f6a3c --- /dev/null +++ b/aoc2021/P14.cpp @@ -0,0 +1,83 @@ +typedef pair PCCI; + +map m; +map cache; // XY,iterations -> cnt letter. + +ULL go2(PC pc, char c, int rounds) { + if(rounds == 0) + return 0; + PCCI pcci(pc,rounds); + if(cache.find(pcci) != cache.end()) { + return cache[pcci]; + } + ULL ret = 0; + char mid = m[pc]; + if(mid == c) + ret++; + ret += go2(PC(pc.first,mid), c, rounds-1); + ret += go2(PC(mid,pc.second), c, rounds-1); + + cache[pcci] = ret; + return ret; +} + +ULL go(string s, char c, int rounds) { + ULL ret = 0; + FORUI(s.size()) { + if(s[i] == c) + ret++; + } + FORUI(s.size()-1) { + PC pc(s[i],s[i+1]); + ret += go2(pc, c, rounds); + } + + return ret; +} + +int main() { + GS(t); // Template + string s, ignore; char c; + while(cin >> s >> ignore >> c) { + m[PC(s[0], s[1])] = c; + } + + // Simulate: + ULL ma = 0, mi = 99999999999999; + for(c = 'A'; c <= 'Z'; c++) { + cache.clear(); + ULL cnt = go(t, c, 40); // 10 for part 1, 40 for part 2 + if(cnt == 0) + continue; + ma = max(ma, cnt); + mi = min(mi, cnt); + } + + /* Part 1: + s = t; cout << s << endl; + FORK(10) { + stringstream ss; + for(int i = 0; i < (int)s.size()-1; i++) { + char c1 = s[i], c2 = s[i+1]; + ss << c1 << m[PC(c1,c2)]; + } + ss << s[s.size()-1]; + s = ss.str(); + //cout << s << endl; + } + // Part 1: + int cnt[26]; FORI(26) cnt[i] = 0; + FORUI(s.size()) { + cnt[s[i]-'A']++; + } + FORI(26) { + if(cnt[i] == 0) + continue; + ma = max(ma, cnt[i]); + mi = min(mi, cnt[i]); + } + */ + cout << "Most common: " << ma << endl; + cout << "Least common: " << mi << endl; + cout << (ma-mi) << endl; +} diff --git a/aoc2021/P15.cpp b/aoc2021/P15.cpp new file mode 100644 index 0000000..267d7de --- /dev/null +++ b/aoc2021/P15.cpp @@ -0,0 +1,62 @@ +int Q[100][100], risk[500][500]; +typedef pair PI3; // risk lv, pos +int nx[4] = {0,0,1,-1}; +int ny[4] = {1,-1,0,0}; + +int height = 0, width, HEIGHT, WIDTH; +int getQ(int x, int y) { + int X = x%width, Y = y%height; + int ret = Q[Y][X]; + int dx = x/width, dy = y/height; + ret += dx + dy; + while(ret >= 10) + ret -= 9; + return ret; +} + +int main() { + string s; + while(cin >> s) { + width = (int)s.size(); + FORX(width) + Q[height][x] = s[x]-'0'; + height++; + } + cout << "Read board size " << width << " x " << height << endl; + + HEIGHT = 5*height; + WIDTH = 5*width; // For part 1 use 1 instead of 5 + FORY(HEIGHT) { + FORX(WIDTH) { + risk[y][x] = -1; + } + } + + // Always add min risk neighbor: + set ready; + ready.insert(PI3(0, PI(0,0))); + + while(risk[HEIGHT-1][WIDTH-1] == -1) { + if(ready.empty()) { + cerr << "ERROR" << endl; + return 0; + } + const PI3 pi3 = *(ready.begin()); + ready.erase(pi3); + const PI &p = pi3.second; + if(risk[p.YY][p.XX] != -1) { + continue; // Already handled + } + int r = pi3.first; + risk[p.YY][p.XX] = r; + // Prep neighbours: + FORI(4) { + int x = p.XX + nx[i]; + int y = p.YY + ny[i]; + if(x >= 0 && y >= 0 && x < WIDTH && y < HEIGHT && risk[y][x] == -1) { + ready.insert(PI3(r+getQ(x, y), PI(x,y))); + } + } + } + cout << risk[HEIGHT-1][WIDTH-1] << endl; +} diff --git a/aoc2021/P16.cpp b/aoc2021/P16.cpp new file mode 100644 index 0000000..c099635 --- /dev/null +++ b/aoc2021/P16.cpp @@ -0,0 +1,130 @@ +string s; int idx = 0, sumVersions = 0; +bool bits[10000]; + +int get(int size) { + int ret= 0; + FORI(size) { + ret = 2*ret + (bits[idx++] ? 1 : 0); + } + return ret; +} + +LL readPacket() { + int version = get(3); + sumVersions += version; + int type = get(3); + cout << "Type: " << type << endl; + if(type == 4) { // Read number: + LL val = 0; + while(true) { + bool last = get(1) == 0; + FORI(4) { + val = 2*val + get(1); + } + if(last) + break; + } + cout << "Read literal " << val << endl; + return val; + } + else { + int lti = get(1); + if(lti == 0) { + int to = get(15) + idx; + LL ret; + if(type == 0) + ret = 0; + else if(type == 1) + ret = 1; + else if(type == 2) + ret = 9999999999999; + else if(type == 3) + ret = -9999999999999; + else if(type == 5) + return readPacket() > readPacket() ? 1 : 0; + else if(type == 6) + return readPacket() < readPacket() ? 1 : 0; + else if(type == 7) + return readPacket() == readPacket() ? 1 : 0; + + while(idx < to) { + cout << "Reading sub-packet because " << idx << " < " << to << endl; + LL val = readPacket(); + if(type == 0) { // SUM! + ret += val; + } + else if(type == 1) { // PRODUCT + ret *= val; + } + else if(type == 2) { // MIN + ret = min(ret, val); + } + else if(type == 3) { // MAX + ret = max(ret, val); + } + } + return ret; + } + else { + int numPackets = get(11); + LL ret; + if(type == 0) + ret = 0; + else if(type == 1) + ret = 1; + else if(type == 2) + ret = 9999999999999; + else if(type == 3) + ret = -9999999999999; + else if(type == 5) + return readPacket() > readPacket() ? 1 : 0; + else if(type == 6) + return readPacket() < readPacket() ? 1 : 0; + else if(type == 7) + return readPacket() == readPacket() ? 1 : 0; + + FORI(numPackets) { + LL val = readPacket(); + if(type == 0) { // SUM! + ret += val; + } + else if(type == 1) { // PRODUCT + ret *= val; + } + else if(type == 2) { // MIN + ret = min(ret, val); + } + else if(type == 3) { // MAX + ret = max(ret, val); + } + } + return ret; + + } + } +} + +int main() { + GS(s); + cout << "Read string of length " << s.size() << endl; + // Build bits; + FORUI(s.size()) { + char c = s[i]; + int x; + if(c >= 'A' && c <= 'F') + x = 10 + c-'A'; + else + x = c-'0'; + int mask = 1 << 3; + FORJ(4) { + bits[idx++] = (x&mask) > 0; + mask >>=1; + } + } + idx = 0; // Ready to read bits + + LL answer2 = readPacket(); + + cout << "Answer 1: " << sumVersions << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2021/P17.cpp b/aoc2021/P17.cpp new file mode 100644 index 0000000..74685ed --- /dev/null +++ b/aoc2021/P17.cpp @@ -0,0 +1,51 @@ +// Reduce input to just the numbers +int main() { + GLL(miX); GLL(maX); GLL(miY); GLL(maY); + cout << "Target area: x: " << miX << " -> " << maX << ", y: " << miY << " -> " << maY << endl; + // Assume target area is x > 0 + + // Part 1: Find max height: + LL answer1 = -1, answer2 = 0; + for(LL vx0 = maX; vx0 > 0; vx0--) { + // Can we even reach target area? + // 1+2+...vx0 = + LL canReach = (vx0+1)*vx0/2; + if(canReach < miX) + break; + cout << "TRY " << vx0; + + for(LL vy0 = miY; vy0 < 9999; vy0++) { // Arbitrary max that seems to work forme. + LL x = 0, y = 0, vx = vx0, vy = vy0, maxY = y; + bool wasEverBelowTarget = false, hit = false; + + // Simulate: + do { + // Update position and velocity: + x += vx; + y += vy; + vx = max((LL)0, vx-1); + vy--; + // Update vars: + maxY = max(maxY, y); + if(x >= miX && x <= maX && y >= miY && y <= maY) { + hit = true; + } + if(y < miY) { + wasEverBelowTarget = true; + } + } while(x <= maX && y >= miY); + + if(hit) { + answer1 = max(answer1, maxY); + answer2++; + cout << " HIT " << answer2 << " on initial v: " << vx0 << ", " << vy0 << endl; + } + if(!wasEverBelowTarget) { + break; // y too big + } + + } // for vy0 + } // for vx0 + cout << "Answer 1: " << answer1 << endl; + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2021/P18.cpp b/aoc2021/P18.cpp new file mode 100644 index 0000000..29e1474 --- /dev/null +++ b/aoc2021/P18.cpp @@ -0,0 +1,256 @@ +string s; +int idx = 0; + +struct P { + P *a, *b, *parent; + LL va, vb; // Used when a and b are null +}; + +void print(P *a) { + if(a == NULL) { + cout << "NULL"; + return; + } + + cout << "["; + if(a->a == NULL) + cout << a->va; + else + print(a->a); + cout << ","; + if(a->b == NULL) + cout << a->vb; + else + print(a->b); + cout << "]"; +} + +LL magnitude(P *a) { + LL left = (a->a == NULL ? a->va : magnitude(a->a)); + LL right = (a->b == NULL ? a->vb : magnitude(a->b)); + return 3*left + 2*right; +} + +void insertUpLeft(P *a, P *child, LL v) { + cout << "Inserting " << v << " up left into "; print(a); cout << endl; + if(a == NULL) { + return; // Nothing to insert up into! + } + + if(child == a->b) { // From the right child: Insert in left side: + if(a->a == NULL) { + a->va+=v; + } + else { + P *c = a->a; + while(c->b != NULL) + c = c->b; + c->vb+=v; + } + } + else { // From the left child: Insert in parents right! + insertUpLeft(a->parent, a, v); + } +} + +void insertUpRight(P *a, P *child, LL v) { + cout << "Inserting " << v << " up right into "; print(a); cout << endl; + if(a == NULL) { + return; // Nothing to insert up into! + } + + if(child == a->a) { // From left child: Insert into right + if(a->b == NULL) { + a->vb+=v; + } + else { + P *c = a->b; + while(c->a != NULL) + c = c->a; + c->va+=v; + } + } + else { + insertUpRight(a->parent, a, v); + } +} + +bool explode(P *a, int lv) { + if(a == NULL || lv > 4) { + cerr << "NULL or Unexpected debth: " << lv << endl; + die(); + } + if(lv <= 3) { + if(a->a != NULL) { + if(explode(a->a, lv+1)) + return true; + } + if(a->b != NULL) { + return explode(a->b, lv+1); + } + return false; + } + else { // lv is 4: explode! + if(a->a != NULL || a->b != NULL) { + cerr << "Non-regular values!" << endl; + die(); + } + cout << "Exploding "; print(a); cout << " at level 4 " << endl; + P* p = a->parent; + insertUpLeft(p, a, a->va); + insertUpRight(p, a, a->vb); + if(a == p->a) { + p->va = 0; // Replace a with 0 + p->a = NULL; + } + else { + p->vb = 0; + p->b = NULL; + } + delete a; + cout << "Explosion done! Parent now: "; print(p); cout << endl; + return true; + } +} + +bool split(P *a) { + if(a == NULL) { + cout << "CANNOT SPLIT NULL" << endl; + die(); + } + if(a->a == NULL) { + if(a->va >= 10) { + cout << "SPLITTING LEFT "; print(a); cout << endl; + P *x = new P; + x->parent = a; + a->a = x; + x->a = x->b = NULL; + x->va = a->va/2; + x->vb = a->va - x->va; + return true; + } + } + if(a->a != NULL) { + if(split(a->a)) + return true; + } + // Left OK. Proceed with right: + if(a->b == NULL) { + if(a->vb >= 10) { + cout << "SPLITTING RIGHT "; print(a); cout << endl; + P *x = new P; + x->parent = a; + a->b = x; + x->a = x->b = NULL; + x->va = a->vb/2; + x->vb = a->vb - x->va; + return true; + } + } + if(a->b != NULL) { + return split(a->b); + } + return false; +} + +P* add(P *a, P *b) { // a and b are not NULL + P *ret = new P; + ret->a = a; + ret->b = b; + ret->parent = NULL; + a->parent = ret; + b->parent = ret; + + cout << "After addition: "; + print(ret); + cout << endl; + + // Reduce: + while(explode(ret, 0) || split(ret)) { + cout << "AFTER REDUCTION: "; print(ret); cout << endl; + } + + return ret; +} + +P* read(LL &v, P *parent) { + char c = s[idx++]; + + if(c == '[') { + P *ret = new P; + ret->parent = parent; + ret->a = read(ret->va, ret); + c = s[idx++]; + if(c != ',') { + cerr << "Expected comma, found: " << c; + die(); + } + ret->b = read(ret->vb, ret); + c = s[idx++]; + if(c != ']') { + cerr << "Expected ], found: " << c; + die(); + } + return ret; + } + else { + // Read value and return null! + v = c-'0'; + while((c = s[idx++]) != ',' && c != ']') { + v = 10*v + (c-'0'); + } + idx--; // Don't walk over last token. + return NULL; + } +} + +vector v; +P* readP() { + if(!(cin >> s)) + return NULL; + v.push_back(s); + idx = 0; + LL ignore; + return read(ignore, NULL); +} + +int main() { + + P *a = NULL, *b; + while((b = readP()) != NULL) { + cout << "Read "; + print(b); + cout << endl; + + if(a == NULL) + a = b; + else { + a = add(a, b); + } + + cout << endl << "Sum now: "; print(a); cout << endl << endl; + } + cout << "Answer 1: " << magnitude(a) << endl; + + // Part 2: + LL answer2 = -1; + for(int i = 0; i < (int)v.size(); i++) { + for(int j = 0; j < (int)v.size(); j++) { + if(i == j) + continue; + LL ignore; + s = v[i]; + idx = 0; + a = read(ignore, NULL); + + s = v[j]; + idx = 0; + b = read(ignore, NULL); + + a = add(a,b); + answer2 = max(answer2, magnitude(a)); + // Compare i and j: + } + } + cout << "Answer 2: " << answer2 << endl; +} diff --git a/aoc2021/P20.cpp b/aoc2021/P20.cpp new file mode 100644 index 0000000..3295942 --- /dev/null +++ b/aoc2021/P20.cpp @@ -0,0 +1,72 @@ +string mesh, image; +int width, height = 0, allOn = false; + +bool get(int x, int y) { + if(x < 0 || y < 0 || x >= width || y >= height) + return allOn; + return image[width*y + x] == '#'; +} + +void transform() { + int w2 = width+2, h2 = height+2; + stringstream ss; + FORY(h2) { + FORX(w2) { + // Find index: + int idx = 0; + for(int yy = y-1; yy <= y+1; yy++) { + for(int xx = x-1; xx <= x+1; xx++) { + idx <<= 1; + if(get(xx-1, yy-1)) + idx++; + } + } + ss << mesh[idx]; + } + } + image = ss.str(); + width = w2; + height = h2; + if(mesh[0] == '#') + allOn = !allOn; +} + +void print() { + int on = 0; + cout << endl; + FORY(height) { + FORX(width) { + if(image[y*width + x] == '#') { + cout << '#'; + on++; + } + else { + cout << '.'; + } + } + cout << endl; + } + cout << endl << "Size " << width << " x " << height << " Total on: " << on << endl; +} + +int main() { + string s; + getline(cin, mesh); + stringstream ss; + getline(cin, s); // Empty line. + while(getline(cin, s)) { + width = (int)s.size(); + ss << s; + height++; + } + image = ss.str(); + //cout << "Single line: " << image << endl; + cout << "Initial image:" << endl; + print(); + + FORI(50) { // 2 for part 1, 50 for part 2 + transform(); + cout << "After iteration " << (i+1) << ":" << endl; + print(); + } +} diff --git a/aoc2021/P21.cpp b/aoc2021/P21.cpp new file mode 100644 index 0000000..8b47a26 --- /dev/null +++ b/aoc2021/P21.cpp @@ -0,0 +1,149 @@ +//Remove all but starting positions from input. +int pos[2]; //3 4 5 6 7 8 9 +int rolls[7] = {1,3,6,7,6,3,1}; + +// Dynamic programming: Number of ways to at most get this amount of points: +// pos 1[0;9] pos 2, points 1[0;23], points 2, turns +// i j x y turn +LL Q[10][10][32][32][38]; + +int main() { + cin >> pos[0] >> pos[1]; + cout << "Start game with player 1 at position " << pos[0] << " and player 2 at " << pos[1] << endl; + pos[0]--; + pos[1]--; + + // Initial setup for 0 points: + FORI(10) { + FORJ(10) { + FORX(32) { + FORY(32) { + Q[i][j][x][y][0] = 0; + } + } + } + } + Q[ pos[0] ][ pos[1] ][ 0 ][ 0 ][ 0 ] = 1; // 1 way to get to start position in turn 0 with 0 points + + for(int turn = 1; turn < 38; turn++) { // At most 38 turns... most likely less + // Player 1 to get points with player 2 having less: + cout << "TURN " << turn << endl; + FORI(10) { // position i for player 1 + FORJ(10) { // position j for player 2 + FORX(32) { // player 1 x points + FORY(32) { // player 2 y points + // Find out how many ways we can get to this state in turn: + Q[i][j][x][y][turn] = 0; + if(x >= 21 && y >= 21) { + continue; // Game stopped as soon as one of them won. + } + + if(turn%2 == 1) { // Player 1 moved + if(y >= 21) + continue; // Player 2 already won + for(int rollI = 0; rollI < 7; rollI++) { + int roll = rollI+3; + LL mult = rolls[rollI]; + int prevPosition = (i-roll+10)%10; + int prevPoints = x-(i+1); // current position x, i+1 points received. + if(prevPoints < 0 || prevPoints >= 21) + continue; + Q[i][j][x][y][turn] += mult*Q[prevPosition][j][prevPoints][y][turn-1]; + //if(Q[prevPosition][j][prevPoints][y][turn-1] > 0) cout << mult << " Player 1 prevPos " << (prevPosition+1) << " roll " << roll << " pos " << (i+1) << " -> " << x << " points" << endl; + } + } + else { + if(x >= 21) + continue; // Player 1 already won + for(int rollI = 0; rollI < 7; rollI++) { + int roll = rollI+3; + LL mult = rolls[rollI]; + int prevPosition = (j-roll+10)%10; + int prevPoints = y-(j+1); // current position y + if(prevPoints < 0 || prevPoints >= 21) + continue; + Q[i][j][x][y][turn] += mult*Q[i][prevPosition][x][prevPoints][turn-1]; + //if(Q[i][prevPosition][x][prevPoints][turn-1]) cout << mult << " Player 2 prevPos " << (prevPosition+1) << " roll " << roll << " pos " << (j+1) << " -> " << y << " points" << endl; + } + } + /*if(Q[i][j][x][y][turn] > 0) { + cout << "Player 1 at " << (i+1) << " with " << x << " points" << endl; + cout << "Player 2 at " << (j+1) << " with " << y << " points" << endl; + cout << "Ways to get here: " << Q[i][j][x][y][turn] << endl; + }//*/ + } + } + } + } + } + + // Find out how many times each player wins: + // Player 1: + LL p1 = 0, p2 = 0; + for(int turn = 1; turn < 38; turn++) { + FORI(10) { // position i for player 1 + FORJ(10) { // position j for player 2 + FORX(32) { // player 1 x points + FORY(32) { // player 2 y points + if(Q[i][j][x][y][turn] < 0) { + cerr << "Unexpected state!" << endl; + die(); + } + if(Q[i][j][x][y][turn] == 0) + continue; + if(x >= 21) { + p1 += Q[i][j][x][y][turn]; + if(y >= 21) { + cerr << "Unexpected state!" << endl; + die(); + } + } + if(y >= 21) { + p2 += Q[i][j][x][y][turn]; + if(x >= 21) { + cerr << "Unexpected state!" << endl; + die(); + } + } + } + } + } + } + } + cout << "Player 1 wins in: " << p1 << endl; + cout << "Player 2 wins in: " << p2 << endl; + + +} + +/* Part 1: +int pos[2], points[2] = {0,0}, d = -1, numRolls = 0; + +int roll() { + d++; + if(d == 100) + d = 0; + numRolls++; + return d+1; +} + +int main() { + cin >> pos[0] >> pos[1]; + pos[0]--; + pos[1]--; + + int player = 0; + while(points[0] < 1000 && points[1] < 1000) { // 1000 for part 1 + int rolled = roll() + roll() + roll(); + pos[player] = (pos[player]+rolled)%10; + + cout << "Player " << (player+1) << " rolled total " << rolled << " and moved to " << (pos[player]+1) << endl; + + points[player] += pos[player]+1; + player = 1-player; + } + int winner = 1-player; // winner + cout << "Player " << (winner+1) << " wins with " << points[winner] << " points." << endl; + cout << "Rolls: " << numRolls << endl; + cout << (numRolls * points[1-winner]) << endl; + */ diff --git a/aoc2021/P22.cpp b/aoc2021/P22.cpp new file mode 100644 index 0000000..92e0a64 --- /dev/null +++ b/aoc2021/P22.cpp @@ -0,0 +1,119 @@ +// Clean up input by removing all non-numbers and "on" "off" +struct T { + LL x1, x2, y1, y2, z1, z2; + + T(LL _x1, LL _x2, LL _y1, LL _y2, LL _z1, LL _z2) { + x1 = _x1; x2 = _x2; + y1 = _y1; y2 = _y2; + z1 = _z1; z2 = _z2; + } + + T(const T &t) { + x1=t.x1; x2=t.x2; + y1=t.y1; y2=t.y2; + z1=t.z1; z2=t.z2; + } + + bool intersects(const T &t) const { + if(x2 < t.x1 || y2 < t.y1 || z2 < t.z1) + return false; + if(t.x2 < x1 || t.y2 < y1 || t.z2 < z1) + return false; + return true; + } + + T intersection(const T &t) const { + T ret(max(x1,t.x1), min(x2,t.x2), + max(y1,t.y1), min(y2,t.y2), + max(z1,t.z1), min(z2,t.z2)); + return ret; + } + + LL size() const { + return (x2-x1+1)*(y2-y1+1)*(z2-z1+1); + } +}; + +ostream& operator<<(ostream& os, const T& t) +{ + os << '[' << t.x1 << ';' << t.x2 << ", " << t.y1 << ';' << t.y2 <<", " << t.z1 << ';' << t.z2 << ']'; + return os; +} + +vector add, sub; + +LL computeSize() { + LL ret = 0; + FORIT(vector, add) { + ret+=it->size(); + } + FORIT(vector, sub) { + ret-=it->size(); + } + return ret; +} + +void off(const T &t) { + // For all in add, include the intersection in sub! + vector toSub; + FORIT(vector, add) { + T x = *it; + if(x.intersects(t)) { + toSub.push_back(x.intersection(t)); + } + } + // For all in sub, include the intersection in add! + FORIT(vector, sub) { + T x = *it; + if(x.intersects(t)) { + add.push_back(x.intersection(t)); + } + } + FORIT(vector, toSub) { + sub.push_back(*it); + } +} + +void on(const T &t) { + off(t); + add.push_back(t); +} + +void printState() { + cout << "ADD" << endl; + FORIT(vector, add) { + cout << *it << endl; + } + cout << "REM" << endl; + FORIT(vector, sub) { + cout << *it << endl; + } + cout << "SIZE " << computeSize() << endl; +} + +int main() { + LL x1, x2, y1, y2, z1, z2; string op; + cout << "Initial size: " << computeSize() << endl; + while(cin >> op >> x1 >> x2 >> y1 >> y2 >> z1 >> z2) { + if(op == "on") { + T t(x1, x2, y1, y2, z1, z2); + on(t); + //cout << "Turned on " << t << "." << endl; + //printState(); + } + else { // off + T t(x1, x2, y1, y2, z1, z2); + off(t); + //cout << "Turned off " << t << "." << endl; + //printState(); + } + } + + LL answer = computeSize(); + cout << "Answer 2: " << answer << endl; + T answer1Box(-50,50,-50,50,-50,50); + off(answer1Box); + LL smallerAnswer = computeSize(); + + cout << "Answer 1: " << (answer-smallerAnswer) << endl; +} diff --git a/aoc2021/run.sh b/aoc2021/run.sh new file mode 100755 index 0000000..fff7fb7 --- /dev/null +++ b/aoc2021/run.sh @@ -0,0 +1,37 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.bin + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +echo "Compiling $cppFile ..." 1>&2 +cat top.cpp P$1.cpp > tmp.cpp +g++ -o2 -Wall tmp.cpp -o $exeFile +if [ $? -ne 0 ] +then + echo "Compile error. Stop." 1>&2 + exit 3 +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2021/top.cpp b/aoc2021/top.cpp new file mode 100644 index 0000000..f4151cf --- /dev/null +++ b/aoc2021/top.cpp @@ -0,0 +1,74 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORZ(N) for(int z = 0; z < N; ++z) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GLL(N) long long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; +#define GC(N) char N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";} diff --git a/aoc2022/run.sh b/aoc2022/run.sh new file mode 100755 index 0000000..b3ff98d --- /dev/null +++ b/aoc2022/run.sh @@ -0,0 +1,48 @@ +(set -o igncr) 2>/dev/null && set -o igncr; # this comment is needed + +if [ "$#" -lt 1 ]; then + echo "Usage: $0 program_id (111, 112, etc.) [test_file_id] ([a], b, ...)" >&2 + exit 1 +fi + +testFile=P$1a.txt +if [ "$#" -eq 2 ]; then + testFile=P$1$2.txt +fi + +cppFile=P$1.cpp +exeFile=P$1.exe + +if [ ! -f "$cppFile" ] +then + echo "Error: File $cppFile not found!" + exit 2 +fi +if [ ! -f "$testFile" ] +then + echo "Error: File $testFile not found!" + exit 2 +fi + +timeCPP=`stat -c "%Y" $cppFile` +timeA=0 +if [ -f $exeFile ] +then +timeA=`stat -c "%Y" $exeFile` +fi + +if [ $timeA -lt $timeCPP ] +then + echo "Compiling $cppFile ..." 1>&2 + cat top.cpp P$1.cpp > tmp.cpp + g++ -Wall tmp.cpp -o $exeFile + if [ $? -ne 0 ] + then + echo "Compile error. Stop." 1>&2 + exit 3 + fi + cat tmp.cpp > /dev/clipboard +fi + +echo "Running ./$exeFile < $testFile" 1>&2 +./$exeFile < $testFile diff --git a/aoc2022/top.cpp b/aoc2022/top.cpp new file mode 100644 index 0000000..bdf6a51 --- /dev/null +++ b/aoc2022/top.cpp @@ -0,0 +1,71 @@ +// IO: +#include +#include +// Data structures: +#include +#include +#include +#include +#include +#include +// Functions: +#include +#include +#include +#include +#include +#define _USE_MATH_DEFINES +#include +#include + +using namespace std; + +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MAX(a,b) ((b) < (a) ? (a) : (b)) +#define ABS(a) ((a) < 0 ? -(a) : (a)) + +#define FORCAS int cases; cin >> cases; for(int cas = 0; cas < cases; ++cas) +#define FORI(N) for(int i = 0; i < N; ++i) +#define FORJ(N) for(int j = 0; j < N; ++j) +#define FORK(N) for(int k = 0; k < N; ++k) +#define FORX(N) for(int x = 0; x < N; ++x) +#define FORY(N) for(int y = 0; y < N; ++y) +#define FORUI(N) for(unsigned int i = 0; i < N; ++i) +#define FORUJ(N) for(unsigned int j = 0; j < N; ++j) +#define FORUK(N) for(unsigned int k = 0; k < N; ++k) +#define FORUX(N) for(unsigned int x = 0; x < N; ++x) +#define FORUY(N) for(unsigned int y = 0; y < N; ++y) +#define FORIT(T, N) for(T::const_iterator it = N.begin(); it != N.end(); ++it) +#define FORIT2(T, N) for(T::const_iterator it2 = N.begin(); it2 != N.end(); ++it2) +#define GI(N) int N; cin >> N; +#define GL(N) long N; cin >> N; +#define GD(N) double N; cin >> N; +#define GS(N) string N; cin >> N; + +typedef unsigned long long ULL; +typedef long long LL; +typedef long double LD; + +typedef pair PI; +typedef pair PL; +typedef pair PLL; +typedef pair PULL; +typedef pair PD; +typedef pair PSI; +typedef pair PS; +typedef pair PIS; +typedef pair PULLS; +typedef pair PIC; +typedef pair PC; +typedef pair PCI; + +typedef PI Point; +typedef PD Point2D; +#define XX first +#define YY second +#define P1 first +#define P2 second + +void die() {int *a = NULL; a[3] = 2;} + +void dieSlowly() {while(true)cerr << "NOO!";}