Add part 2 solution for day 11

master
Nick Krichevsky 2020-12-11 01:31:29 -05:00
parent 2db2d41a5d
commit 4b353e9bda
2 changed files with 95 additions and 20 deletions

15
day11/Makefile Normal file
View File

@ -0,0 +1,15 @@
CC=g++
BIN_NAME=day11
CCFLAGS=-o $(BIN_NAME) -g -std=c++17
LDFLAGS=-lfolly
.PHONY: all, clean
all: $(BIN_NAME)
clean:
rm -f $(BIN_NAME)
$(BIN_NAME): day11.cpp
$(CC) $(CCFLAGS) $(LDFLAGS) day11.cpp

View File

@ -13,6 +13,8 @@
constexpr char EMPTY_CHAR = 'L'; constexpr char EMPTY_CHAR = 'L';
constexpr char FLOOR_CHAR = '.'; constexpr char FLOOR_CHAR = '.';
constexpr char OCCUPIED_CHAR = '#'; constexpr char OCCUPIED_CHAR = '#';
constexpr int PART_1_OCCUPIED_THRESHOLD = 4;
constexpr int PART_2_OCCUPIED_THRESHOLD = 5;
std::vector<std::string> readInput(const std::string &filename) { std::vector<std::string> readInput(const std::string &filename) {
std::vector<std::string> input; std::vector<std::string> input;
@ -25,7 +27,15 @@ std::vector<std::string> readInput(const std::string &filename) {
return input; return input;
} }
std::vector<char> getNeighbors(const std::vector<std::string> &state, int row, int column) { void printState(const std::vector<std::string> &state) {
for (const std::string &row : state) {
std::cout << row << std::endl;
}
std::cout << " " << std::endl;
}
std::vector<char> getPart1Neighbors(const std::vector<std::string> &state, int row, int column) {
std::vector<char> neighbors; std::vector<char> neighbors;
for (int dRow = -1; dRow <= 1; dRow++) { for (int dRow = -1; dRow <= 1; dRow++) {
for (int dCol = -1; dCol <= 1; dCol++) { for (int dCol = -1; dCol <= 1; dCol++) {
@ -35,7 +45,7 @@ std::vector<char> getNeighbors(const std::vector<std::string> &state, int row, i
int candidateRow = row + dRow; int candidateRow = row + dRow;
int candidateCol = column + dCol; int candidateCol = column + dCol;
if (candidateRow < 0 || candidateRow >= state.size() || candidateRow < 0 || if (candidateRow < 0 || candidateRow >= state.size() || candidateCol < 0 ||
candidateCol >= state.at(candidateRow).size()) { candidateCol >= state.at(candidateRow).size()) {
continue; continue;
} }
@ -48,39 +58,80 @@ std::vector<char> getNeighbors(const std::vector<std::string> &state, int row, i
return neighbors; return neighbors;
} }
char applyRules(const std::vector<std::string> &state, int row, int column) { template <typename T>
std::vector<char> neighbors = getNeighbors(state, row, column); int sign(T val) {
char item = state.at(row).at(column); // Taken from https://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
return (T(0) < val) - (val < T(0));
}
/**
* Extend a pair in all directions it extends - e.g. (1, 0) becomes (2,0)
* @tparam T The type that the pair holds
* @param vec The vector to extend
*/
template <typename T>
void extendVector(std::pair<T, T> &vec) {
vec.first += sign(vec.first);
vec.second += sign(vec.second);
}
std::vector<char> getPart2Neighbors(const std::vector<std::string> &state, int row, int column) {
std::vector<char> neighbors;
for (int dRow = -1; dRow <= 1; dRow++) {
for (int dCol = -1; dCol <= 1; dCol++) {
if (dRow == 0 && dCol == 0) {
continue;
}
std::pair<int, int> deltaVector(dRow, dCol);
char neighbor = FLOOR_CHAR;
// Keep projecting our ray until we hit a non floor char
while (neighbor == FLOOR_CHAR) {
int candidateRow = row + deltaVector.first;
int candidateCol = column + deltaVector.second;
if (candidateRow < 0 || candidateRow >= state.size() || candidateCol < 0 ||
candidateCol >= state.at(candidateRow).size()) {
break;
}
neighbor = state.at(candidateRow).at(candidateCol);
extendVector(deltaVector);
}
neighbors.push_back(neighbor);
}
}
return neighbors;
}
char applyRules(const std::vector<char> &neighbors, char seatState, int occupiedThreshold) {
int numOccupied = int numOccupied =
std::count_if(neighbors.begin(), neighbors.end(), [](char neighbor) { return neighbor == OCCUPIED_CHAR; }); std::count_if(neighbors.begin(), neighbors.end(), [](char neighbor) { return neighbor == OCCUPIED_CHAR; });
if (item == EMPTY_CHAR && numOccupied == 0) { if (seatState == EMPTY_CHAR && numOccupied == 0) {
return OCCUPIED_CHAR; return OCCUPIED_CHAR;
} else if (item == OCCUPIED_CHAR && numOccupied >= 4) { } else if (seatState == OCCUPIED_CHAR && numOccupied >= occupiedThreshold) {
return EMPTY_CHAR; return EMPTY_CHAR;
} else { } else {
return item; return seatState;
} }
} }
void printState(const std::vector<std::string> &state) { int runSimulation(
for (const std::string &row : state) { const std::vector<std::string> &input, int occupiedThreshold,
std::cout << row << std::endl; std::function<std::vector<char>(const std::vector<std::string>, int, int)> getNeighbors) {
}
std::cout << " " << std::endl;
}
int part1(const std::vector<std::string> &input) {
std::vector<std::string> state(input); std::vector<std::string> state(input);
std::vector<std::string> nextState(input.size(), std::string(input.at(0).size(), ' ')); std::vector<std::string> nextState(input.size(), std::string(input.at(0).size(), ' '));
while (state != nextState) { for (int count = 0; state != nextState; count++) {
for (int i = 0; i < state.size(); i++) { for (int i = 0; i < state.size(); i++) {
for (int j = 0; j < input.at(i).size(); j++) { for (int j = 0; j < input.at(i).size(); j++) {
char res = applyRules(state, i, j); std::vector<char> neighbors = getNeighbors(state, i, j);
char res = applyRules(neighbors, state.at(i).at(j), occupiedThreshold);
nextState.at(i).at(j) = res; nextState.at(i).at(j) = res;
} }
} }
printState(state);
std::swap(state, nextState); std::swap(state, nextState);
} }
@ -89,6 +140,14 @@ int part1(const std::vector<std::string> &input) {
}); });
} }
int part1(const std::vector<std::string> &input) {
return runSimulation(input, PART_1_OCCUPIED_THRESHOLD, getPart1Neighbors);
}
int part2(const std::vector<std::string> &input) {
return runSimulation(input, PART_2_OCCUPIED_THRESHOLD, getPart2Neighbors);
}
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if (argc != 2) { if (argc != 2) {
std::cerr << argv[0] << " <input_file>" << std::endl; std::cerr << argv[0] << " <input_file>" << std::endl;
@ -97,5 +156,6 @@ int main(int argc, char *argv[]) {
auto input = readInput(argv[1]); auto input = readInput(argv[1]);
std::cout << part1(input) << std::endl; // std::cout << part1(input) << std::endl;
std::cout << part2(input) << std::endl;
} }