Clean up day 20 part 2

master
Nick Krichevsky 2020-12-24 18:29:13 -05:00
parent 53e157aefe
commit 1b851979a5
2 changed files with 42 additions and 49 deletions

View File

@ -1,6 +1,6 @@
CC=g++ CC=g++
BIN_NAME=day20 BIN_NAME=day20
CCFLAGS=-o $(BIN_NAME) -g -std=c++17 CCFLAGS=-o $(BIN_NAME) -O2 -std=c++17
LDFLAGS=-lfolly LDFLAGS=-lfolly
.PHONY: all, clean .PHONY: all, clean

View File

@ -182,7 +182,7 @@ class CameraFrame {
/** /**
* Remove the border of this frame * Remove the border of this frame
*/ */
void removeBorder() { void removeFrameBorder() {
std::vector<std::string> outFrame; std::vector<std::string> outFrame;
std::transform( std::transform(
this->frame.cbegin() + 1, this->frame.cbegin() + 1,
@ -514,14 +514,11 @@ std::map<std::pair<int, int>, CameraFrame> findLinedUpArrangement(const std::vec
throw std::invalid_argument("No solution for input"); throw std::invalid_argument("No solution for input");
} }
long part1(const std::vector<CameraFrame> &frames) { /**
int boardSize = calculateBoardSize(frames); * Get the size of a monster, given a strong representing one.
auto board = findLinedUpArrangement(frames); * @param monster The monster string
return 1L * board.at(std::make_pair(0, 0)).getID() * board.at(std::make_pair(0, boardSize - 1)).getID() * * @return std::pair<int, int> The height and width of the monster, as a pair.
board.at(std::make_pair(boardSize - 1, 0)).getID() * */
board.at(std::make_pair(boardSize - 1, boardSize - 1)).getID();
}
std::pair<int, int> getMonsterDimensions(const std::string &monster) { std::pair<int, int> getMonsterDimensions(const std::string &monster) {
int height = std::count(monster.cbegin(), monster.cend(), '\n') + 1; int height = std::count(monster.cbegin(), monster.cend(), '\n') + 1;
std::vector<std::string> lines; std::vector<std::string> lines;
@ -536,11 +533,20 @@ std::pair<int, int> getMonsterDimensions(const std::string &monster) {
return std::make_pair(height, width); return std::make_pair(height, width);
} }
/**
* Join a board's frames together into one big board.
* @param board The board to join.
* @param maxRow The highest row in the board
* @param maxCol The highest col in the board
* @return std::vector<std::string> The joined board
*/
std::vector<std::string> joinFullBoard( std::vector<std::string> joinFullBoard(
const std::map<std::pair<int, int>, CameraFrame> &board, int maxRow, int maxCol) { const std::map<std::pair<int, int>, CameraFrame> &board, int maxRow, int maxCol) {
std::vector<std::string> outBoard; std::vector<std::string> outBoard;
// Get an arbitrary frame - doesn't matter what it is, we just need a size.
auto firstFrame = *board.begin();
for (int i = 0; i < maxRow; i++) { for (int i = 0; i < maxRow; i++) {
for (int frameRow = 0; frameRow < NUM_CAMERA_LINES - 2; frameRow++) { for (int frameRow = 0; frameRow < firstFrame.second.getFrame().size(); frameRow++) {
outBoard.push_back(""); outBoard.push_back("");
std::string &outRow = outBoard.back(); std::string &outRow = outBoard.back();
for (int j = 0; j < maxCol; j++) { for (int j = 0; j < maxCol; j++) {
@ -554,26 +560,24 @@ std::vector<std::string> joinFullBoard(
return outBoard; return outBoard;
} }
/**
* Get the number of characters that contain a monster, within the monster dimensions, starting at (row, col). This only scans for a single monster.
* @param frame The frame to scan
* @param row The row to start at
* @param col The col to start at
* @return int The number of monster characters in this area.
*/
int getNumMonsterChars(const CameraFrame &frame, int row, int col) { int getNumMonsterChars(const CameraFrame &frame, int row, int col) {
std::pair<int, int> monsterDimensions = getMonsterDimensions(MONSTER_STR); std::pair<int, int> monsterDimensions = getMonsterDimensions(MONSTER_STR);
std::vector<std::string> monsterLines; std::vector<std::string> monsterLines;
folly::split("\n", MONSTER_STR, monsterLines); folly::split("\n", MONSTER_STR, monsterLines);
std::cout << std::endl;
int total = 0; int total = 0;
for (int i = 0; i < monsterDimensions.first; i++) { for (int i = 0; i < monsterDimensions.first; i++) {
bool foundMonster = true; bool foundMonster = true;
for (int j = 0; j < monsterDimensions.second; j++) { for (int j = 0; j < monsterDimensions.second; j++) {
char monsterChar = monsterLines.at(i).at(j); char monsterChar = monsterLines.at(i).at(j);
char frameChar = frame.getFrame().at(row + i).at(col + j); char frameChar = frame.getFrame().at(row + i).at(col + j);
if (monsterChar == '#' && frameChar == '#') {
std::cout << 'O';
} else if (monsterChar == '#') {
std::cout << 'o';
} else {
std::cout << frameChar;
}
if (monsterChar == MONSTER_SIGNAL_CHAR && frameChar != MONSTER_SIGNAL_CHAR) { if (monsterChar == MONSTER_SIGNAL_CHAR && frameChar != MONSTER_SIGNAL_CHAR) {
foundMonster = false; foundMonster = false;
break; break;
@ -583,64 +587,52 @@ int getNumMonsterChars(const CameraFrame &frame, int row, int col) {
} }
// If this line didn't find a monster, there can't be any true monster chars // If this line didn't find a monster, there can't be any true monster chars
if (!foundMonster) { if (!foundMonster) {
std::cout << std::endl << 0 << std::endl;
return 0; return 0;
} }
std::cout << std::endl;
} }
std::cout << total << std::endl;
return total; return total;
} }
long part2(const std::vector<CameraFrame> &frames) { long part1(const std::map<std::pair<int, int>, CameraFrame> &board, int boardSize) {
int boardSize = calculateBoardSize(frames); return 1L * board.at(std::make_pair(0, 0)).getID() * board.at(std::make_pair(0, boardSize - 1)).getID() *
auto board = findLinedUpArrangement(frames); board.at(std::make_pair(boardSize - 1, 0)).getID() *
board.at(std::make_pair(boardSize - 1, boardSize - 1)).getID();
}
long part2(const std::map<std::pair<int, int>, CameraFrame> &rawBoard, int boardSize) {
// Remove all of the borders from the board
std::map<std::pair<int, int>, CameraFrame> board(rawBoard);
std::for_each(board.begin(), board.end(), [](std::pair<const std::pair<int, int>, CameraFrame> &frame) { std::for_each(board.begin(), board.end(), [](std::pair<const std::pair<int, int>, CameraFrame> &frame) {
std::cout << frame.first.first << ", " << frame.first.second << " " << frame.second.getID() << std::endl; frame.second.removeFrameBorder();
}); });
printBoard(board, boardSize, boardSize);
std::for_each(board.begin(), board.end(), [](std::pair<const std::pair<int, int>, CameraFrame> &frame) {
frame.second.removeBorder();
});
printBoard(board, boardSize, boardSize, -2);
std::pair<int, int> monsterDimensions = getMonsterDimensions(MONSTER_STR); std::pair<int, int> monsterDimensions = getMonsterDimensions(MONSTER_STR);
auto fullBoard = joinFullBoard(board, boardSize, boardSize); auto fullBoard = joinFullBoard(board, boardSize, boardSize);
auto fullBoardFrame = CameraFrame(0, fullBoard); auto fullBoardFrame = CameraFrame(0, fullBoard);
// TODO: This should not be hardcoded
std::for_each(fullBoardFrame.getFrame().cbegin(), fullBoardFrame.getFrame().cend(), [](const std::string &frame) {
std::cout << frame << std::endl;
});
std::cout << std::endl;
int totalSignalChars = int totalSignalChars =
std::accumulate(fullBoard.cbegin(), fullBoard.cend(), 0, [](int total, const std::string &boardRow) { std::accumulate(fullBoard.cbegin(), fullBoard.cend(), 0, [](int total, const std::string &boardRow) {
return total + std::count(boardRow.cbegin(), boardRow.cend(), MONSTER_SIGNAL_CHAR); return total + std::count(boardRow.cbegin(), boardRow.cend(), MONSTER_SIGNAL_CHAR);
}); });
std::cout << totalSignalChars << std::endl;
auto transforms = TransformGenerator(fullBoardFrame); auto transforms = TransformGenerator(fullBoardFrame);
for (auto it = transforms.cbegin(); it != transforms.cend(); it++) { for (auto it = transforms.cbegin(); it != transforms.cend(); it++) {
auto transformedFrame = (*it)(); auto transformedFrame = (*it)();
std::for_each(
transformedFrame.getFrame().cbegin(), transformedFrame.getFrame().cend(), [](const std::string &frame) {
std::cout << frame << std::endl;
});
int totalMonsterChars = 0; int totalMonsterChars = 0;
for (int i = 0; i < fullBoard.size() - monsterDimensions.first; i++) { for (int i = 0; i < fullBoard.size() - monsterDimensions.first; i++) {
for (int j = 0; j < fullBoard.at(0).size() - monsterDimensions.second; j++) { for (int j = 0; j < fullBoard.at(0).size() - monsterDimensions.second; j++) {
int monsterChars = getNumMonsterChars(transformedFrame, i, j); int monsterChars = getNumMonsterChars(transformedFrame, i, j);
totalMonsterChars += monsterChars; totalMonsterChars += monsterChars;
std::cout << std::endl << std::endl;
} }
} }
// Only one orientation will match a monster
if (totalMonsterChars > 0) { if (totalMonsterChars > 0) {
std::cout << totalMonsterChars << std::endl;
return totalSignalChars - totalMonsterChars; return totalSignalChars - totalMonsterChars;
} }
} }
throw std::invalid_argument("No valid solution"); throw std::invalid_argument("No valid solution");
} }
@ -652,8 +644,9 @@ int main(int argc, char *argv[]) {
auto input = readInput(argv[1]); auto input = readInput(argv[1]);
auto parsedInput = parseInput(input); auto parsedInput = parseInput(input);
auto frame = parsedInput.at(0); int boardSize = calculateBoardSize(parsedInput);
auto board = findLinedUpArrangement(parsedInput);
std::cout << part1(parsedInput) << std::endl; std::cout << part1(board, boardSize) << std::endl;
std::cout << part2(parsedInput) << std::endl; std::cout << part2(board, boardSize) << std::endl;
} }