diff options
-rw-r--r-- | src/2017/day10/aoc.cpp | 79 | ||||
-rw-r--r-- | src/2017/day10/aoc.h | 1 | ||||
-rw-r--r-- | src/2017/day14/README.md | 19 | ||||
-rw-r--r-- | src/2017/day14/aoc.cpp | 1 | ||||
-rw-r--r-- | src/2017/day14/aoc.h | 1 | ||||
-rw-r--r-- | src/2017/day15/README.md | 39 | ||||
-rw-r--r-- | test/test_2017.cpp | 6 |
7 files changed, 139 insertions, 7 deletions
diff --git a/src/2017/day10/aoc.cpp b/src/2017/day10/aoc.cpp index b6b617f..0d0d5a4 100644 --- a/src/2017/day10/aoc.cpp +++ b/src/2017/day10/aoc.cpp @@ -1,4 +1,6 @@ #include "aoc.h" +#include <deque> +#include <set> namespace aoc2017 { @@ -102,7 +104,19 @@ static void reduce(uint8_t dense[16], uint8_t sparse[256]) { } } -int knot_hash(line_view file, int total) { +static void binary_grid(char hexdigit[33], char* grid) { + const char* b09[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001"}; + const char* baf[] = {"1010", "1011", "1100", "1101", "1110", "1111"}; + + for (int i = 0; i < 32; i++) { + char c = hexdigit[i]; + memcpy(grid + 4 * i, c >= '0' && c <= '9' ? b09[c - '0'] : baf[c - 'a'], 4); + } + + // printf("%s\n", binary); +} + +int knot_hash(line_view file, int total, char* grid = nullptr) { const char trail[] = {17, 31, 73, 47, 23}; char* input = (char*)malloc(file.length - 1 + 5); memcpy(input, file.line, file.length - 1); @@ -125,8 +139,10 @@ int knot_hash(line_view file, int total) { for (int i = 0; i < 16; i++) { sprintf(hexdigit + i * 2, "%02x", dense[i]); } - // printf("%s\n", hexdigit); + if (grid != nullptr) { + binary_grid(hexdigit, grid); + } return 0; } @@ -134,4 +150,63 @@ std::pair<int64_t, int64_t> day10(line_view file) { knot_hash(file, 64); return {knot_hash_once(file), 0}; } + +struct pos { + int r; + int c; + + friend bool operator==(pos p1, pos p2) { return p1.r == p2.r && p1.c == p2.c; } + friend bool operator<(pos p1, pos p2) { return p1.r < p2.r ? true : p1.r > p2.r ? false : p1.c < p2.c; } +}; + +void floodfill(int x, pos p, char grid[128][128], int fill[128][128]) { + std::deque<pos> q; + q.push_back(p); + + auto is_valid = [](pos p) -> bool { return p.r >= 0 && p.r < 128 && p.c >= 0 && p.c < 128; }; + while (!q.empty()) { + auto s = q.size(); + while (s-- > 0) { + auto p0 = q.front(); + q.pop_front(); + + fill[p0.r][p0.c] = x; + + pos ns[] = {{p0.r, p0.c + 1}, {p0.r, p0.c - 1}, {p0.r - 1, p0.c}, {p0.r + 1, p0.c}}; + for (auto& n : ns) { + if (is_valid(n) && grid[n.r][n.c] == '1' && fill[n.r][n.c] == 0) { + q.push_back(n); + } + } + } + } +} + +std::pair<int64_t, int64_t> day14(line_view) { + char buf[30]; + const char* key = "oundnydw"; + // const char* key = "flqrgnkx"; + char grid[128][128]; + for (int i = 0; i < 128; i++) { + memset(buf, 0, 30); + sprintf(buf, "%s-%d\n", key, i); + knot_hash(buf, 64, grid[i]); + } + + int t0{0}; + int fill[128][128] = {{0}}; + + int t1{0}; + for (int r = 0; r < 128; r++) { + for (int c = 0; c < 128; c++) { + char x = grid[r][c]; + t0 += x - '0'; + if (x == '1' && fill[r][c] == 0) { + floodfill(++t1, {r, c}, grid, fill); + } + } + } + + return {t0, t1}; +} } // namespace aoc2017 diff --git a/src/2017/day10/aoc.h b/src/2017/day10/aoc.h index a4cdca8..33581b9 100644 --- a/src/2017/day10/aoc.h +++ b/src/2017/day10/aoc.h @@ -12,4 +12,5 @@ struct knot { std::pair<int64_t, int64_t> day10(line_view); +std::pair<int64_t, int64_t> day14(line_view); } diff --git a/src/2017/day14/README.md b/src/2017/day14/README.md index 301e2cb..f0d7fa8 100644 --- a/src/2017/day14/README.md +++ b/src/2017/day14/README.md @@ -26,3 +26,22 @@ In this example, 8108 squares are used across the entire 128x128 grid. Given your actual key string, how many squares are used? Your puzzle input is oundnydw. + +--- Part Two --- +Now, all the defragmenter needs to know is the number of regions. A region is a group of used squares that are all adjacent, not including diagonals. Every used square is in exactly one region: lone used squares form their own isolated regions, while several adjacent squares all count as a single region. + +In the example above, the following nine regions are visible, each marked with a distinct digit: + +11.2.3..--> +.1.2.3.4 +....5.6. +7.8.55.9 +.88.5... +88..5..8 +.8...8.. +88.8.88.--> +| | +V V +Of particular interest is the region marked 8; while it does not appear contiguous in this small view, all of the squares marked 8 are connected when considering the whole 128x128 grid. In total, in this example, 1242 regions are present. + +How many regions are present given your key string? diff --git a/src/2017/day14/aoc.cpp b/src/2017/day14/aoc.cpp index 925b403..376a922 100644 --- a/src/2017/day14/aoc.cpp +++ b/src/2017/day14/aoc.cpp @@ -2,5 +2,4 @@ namespace aoc2017 { -std::pair<int64_t, int64_t> day14(line_view) { return {0, 0}; } } // namespace aoc2017 diff --git a/src/2017/day14/aoc.h b/src/2017/day14/aoc.h index d346d57..b3a5cb6 100644 --- a/src/2017/day14/aoc.h +++ b/src/2017/day14/aoc.h @@ -3,5 +3,4 @@ #include <vector> namespace aoc2017 { -std::pair<int64_t, int64_t> day14(line_view); } diff --git a/src/2017/day15/README.md b/src/2017/day15/README.md index e69de29..115ee94 100644 --- a/src/2017/day15/README.md +++ b/src/2017/day15/README.md @@ -0,0 +1,39 @@ +--- Day 15: Dueling Generators --- +Here, you encounter a pair of dueling generators. The generators, called generator A and generator B, are trying to agree on a sequence of numbers. However, one of them is malfunctioning, and so the sequences don't always match. + +As they do this, a judge waits for each of them to generate its next value, compares the lowest 16 bits of both values, and keeps track of the number of times those parts of the values match. + +The generators both work on the same principle. To create its next value, a generator will take the previous value it produced, multiply it by a factor (generator A uses 16807; generator B uses 48271), and then keep the remainder of dividing that resulting product by 2147483647. That final remainder is the value it produces next. + +To calculate each generator's first value, it instead uses a specific starting value as its "previous value" (as listed in your puzzle input). + +For example, suppose that for starting values, generator A uses 65, while generator B uses 8921. Then, the first five pairs of generated values are: + +--Gen. A-- --Gen. B-- + 1092455 430625591 +1181022009 1233683848 + 245556042 1431495498 +1744312007 137874439 +1352636452 285222916 +In binary, these pairs are (with generator A's value first in each pair): + +00000000000100001010101101100111 +00011001101010101101001100110111 + +01000110011001001111011100111001 +01001001100010001000010110001000 + +00001110101000101110001101001010 +01010101010100101110001101001010 + +01100111111110000001011011000111 +00001000001101111100110000000111 + +01010000100111111001100000100100 +00010001000000000010100000000100 +Here, you can see that the lowest (here, rightmost) 16 bits of the third value match: 1110001101001010. Because of this one match, after processing these five pairs, the judge would have added only 1 to its total. + +To get a significant sample, the judge would like to consider 40 million pairs. (In the example above, the judge would eventually find a total of 588 pairs that match in their lowest 16 bits.) + +After 40 million pairs, what is the judge's final count? + diff --git a/test/test_2017.cpp b/test/test_2017.cpp index d7923b9..32e4ffd 100644 --- a/test/test_2017.cpp +++ b/test/test_2017.cpp @@ -149,12 +149,12 @@ TEST_CASE("Packet Scanners", "[2017]") { TEST_CASE("Disk Defragmentation", "[2017]") { line_view lv = load_file("../src/2017/day14/input"); auto p = aoc2017::day14(lv); - REQUIRE(0 == p.first); - REQUIRE(0 == p.second); + REQUIRE(8106 == p.first); + REQUIRE(1164 == p.second); } -TEST_CASE("", "[2017]") { +TEST_CASE("Dueling Generators", "[2017]") { line_view lv = load_file("../src/2017/day15/input"); auto p = aoc2017::day15(lv); REQUIRE(0 == p.first); |