#include #include #include #include #include #include #include #define POSITON_TO_INDEX(x, y) (y * width) + x #define SEARCHBOX_WIDTH 3 #define SEARCHBOX_HEIGTH 3 // Basically floor(SEARCHBOX_WIDTH/2) #define SEARCHBOX_HALF 1 std::ifstream input("input"); std::string wholeFile(std::istreambuf_iterator{input}, {}); uint16_t width, height, length; uint16_t iterateAndFindAvailableRolls(); int main() { width = wholeFile.find('\n'); wholeFile.erase(std::remove(wholeFile.begin(), wholeFile.end(), '\n'), wholeFile.end()); // Need \n for width, for rest it screws with the result length = wholeFile.length(); height = length / width; uint16_t output = 0, totalAvailable = 0; while ((output = iterateAndFindAvailableRolls())) { totalAvailable += output; } std::cout << totalAvailable << std::endl; return 0; } uint16_t iterateAndFindAvailableRolls() { // Range // x = 0 <= currentPosition < width // y = 0 <= currentPosition < height char currentCharacter = ' '; uint16_t x = 0, y = 0; std::vector whereAvailableRollsAre{}; for (uint16_t currentPosition = 0; currentPosition < length; currentPosition++) { currentCharacter = wholeFile.at(currentPosition); if (currentCharacter != '@') { continue; } // Really convenient that integers are floored x = currentPosition % width; y = currentPosition / width; uint8_t neighbourCount = 0; // Just check for 5 since we know middle is definetly @ always for (int16_t index = 0, widthCounter = SEARCHBOX_HALF * -2, currentGlobalIndex = 0, currentX = 0, currentY = 0; index < SEARCHBOX_WIDTH * SEARCHBOX_HEIGTH; index++) { if (neighbourCount == 5) { break; } if (index % SEARCHBOX_WIDTH == 0) { widthCounter++; } // Edge case, corners don't wrap currentX = (x - SEARCHBOX_HALF) + index % SEARCHBOX_WIDTH; currentY = y + widthCounter; if (currentX < 0 || currentX >= width || currentY < 0 || currentY >= height) { continue; } // Make sure index is valid currentGlobalIndex = POSITON_TO_INDEX(currentX, currentY); if (wholeFile.at(currentGlobalIndex) == '@') { neighbourCount++; } } if (neighbourCount < 5) { whereAvailableRollsAre.push_back(currentPosition); } } // I'm sure there is a better way, where yo integrate this // logic with the one above for (uint16_t position : whereAvailableRollsAre) { wholeFile.at(position) = '.'; } return whereAvailableRollsAre.size(); }