87 lines
2.5 KiB
C++
87 lines
2.5 KiB
C++
#include <algorithm>
|
|
#include <cstdint>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
#include <iterator>
|
|
#include <string>
|
|
|
|
#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
|
|
|
|
int main() {
|
|
std::ifstream input("input");
|
|
std::string wholeFile(std::istreambuf_iterator<char>{input}, {});
|
|
|
|
uint16_t width, height, length;
|
|
width = wholeFile.find('\n');
|
|
|
|
// Note for self, std::remove is an algorithm that gets a range and then
|
|
// removes a specific value, however it returns a forward iterator, not the
|
|
// type itself. Neat thing with the iterator is that you can use
|
|
// std::string::erase with it to basically presicion strike specific
|
|
// characters from an existing string. Iterated value must be same as the
|
|
// array(std::string = std::basic_string<char>, hence must use char)
|
|
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;
|
|
|
|
// Range
|
|
// x = 0 <= currentPosition < width
|
|
// y = 0 <= currentPosition < height
|
|
char currentCharacter = ' ';
|
|
uint16_t x = 0, y = 0, totalAvailable = 0;
|
|
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++;
|
|
}
|
|
}
|
|
|
|
totalAvailable += neighbourCount < 5;
|
|
}
|
|
std::cout << totalAvailable << std::endl;
|
|
|
|
return 0;
|
|
}
|