Advertisement
goeyj

Advent of Code: Day 11

Dec 11th, 2020 (edited)
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.77 KB | None | 0 0
  1. #include "../aoc.h"
  2.  
  3. struct Cell {
  4.   char originalState;
  5.   char curState;
  6.   char nextState;
  7.  
  8.   Cell (char value) {
  9.     originalState = value;
  10.     curState = value;
  11.     nextState = value;
  12.   }
  13. };
  14.  
  15. class Automata {
  16. public:
  17.   Automata(std::ifstream input) {
  18.     if (input.is_open()) {
  19.       std::string line;
  20.  
  21.       while(getline(input, line)) {
  22.         std::vector<Cell> row;
  23.         row.reserve(line.length());
  24.         for (char value : line) {
  25.           row.emplace_back(Cell(value));
  26.           if (value == active) { ++activeCount; }
  27.         }
  28.         matrix.emplace_back(row);
  29.       }
  30.  
  31.       input.close();
  32.     }
  33.  
  34.     height = matrix.size();
  35.     width = height ? matrix.at(0).size() : 0;
  36.   }
  37.  
  38.   int activeCells() { return activeCount; }
  39.  
  40.   void stabilize(bool viewNeighborsOnly) {
  41.     bool cellsChanged;
  42.     int minActiveVisible = viewNeighborsOnly ? 4 : 5;
  43.  
  44.     do {
  45.       cellsChanged = false;
  46.       updateState();
  47.  
  48.       for (int i = 0; i < height; ++i) {
  49.         for (int j = 0; j < width; ++j) {
  50.           char curState = matrix[i][j].curState;
  51.  
  52.           if (curState == inactive && countOccupied(i, j, viewNeighborsOnly) == 0) {
  53.             matrix[i][j].nextState = active;
  54.             cellsChanged = true;
  55.             ++activeCount;
  56.           } else if (curState == active && countOccupied(i, j, viewNeighborsOnly) >= minActiveVisible) {
  57.             matrix[i][j].nextState = inactive;
  58.             cellsChanged = true;
  59.             --activeCount;
  60.           } else {
  61.             matrix[i][j].nextState = curState;
  62.           }
  63.         }
  64.       }
  65.     } while (cellsChanged);
  66.   }
  67.  
  68.   void reset() {
  69.     for (int i = 0; i < height; ++i) {
  70.       for (int j = 0; j < width; ++j) {
  71.         if (matrix[i][j].curState == active && matrix[i][j].originalState == inactive) { --activeCount; }
  72.         else if (matrix[i][j].curState == inactive && matrix[i][j].originalState == active) { ++activeCount; }
  73.         matrix[i][j].curState = matrix[i][j].originalState;
  74.         matrix[i][j].nextState = matrix[i][j].originalState;
  75.       }
  76.     }
  77.   }
  78.  
  79. private:
  80.   std::vector<std::vector<Cell>> matrix;
  81.   char active = '#';
  82.   char inactive = 'L';
  83.   int activeCount = 0;
  84.   int height, width;
  85.  
  86.   void updateState() {
  87.     for (int i = 0; i < height; ++i) {
  88.       for (int j = 0; j < width; ++j) {
  89.         matrix[i][j].curState = matrix[i][j].nextState;
  90.       }
  91.     }
  92.   }
  93.  
  94.   int countOccupied(int i, int j, bool viewNeighborsOnly) {
  95.     return viewNeighborsOnly ? countOccupiedNeighbors(i, j) : countOccupiedVisible(i, j);
  96.   }
  97.  
  98.   int countOccupiedNeighbors(int i, int j) {
  99.     int occupiedNeighbors = 0;
  100.  
  101.     // check above
  102.     if (i > 0) {
  103.       if (matrix.at(i-1).at(j).curState == active) ++occupiedNeighbors;
  104.       if (j > 0 && matrix.at(i-1).at(j-1).curState == active) ++occupiedNeighbors;
  105.       if (j < width - 1 && matrix.at(i-1).at(j+1).curState == active) ++occupiedNeighbors;
  106.     }
  107.  
  108.     // check below
  109.     if (i < height - 1) {
  110.       if (matrix.at(i+1).at(j).curState == active) ++occupiedNeighbors;
  111.       if (j > 0 && matrix.at(i+1).at(j-1).curState == active) ++occupiedNeighbors;
  112.       if (j < width - 1 && matrix.at(i+1).at(j+1).curState == active) ++occupiedNeighbors;
  113.     }
  114.  
  115.     // check left and right
  116.     if (j > 0 && matrix.at(i).at(j-1).curState == active) ++occupiedNeighbors;
  117.     if (j < width - 1 && matrix.at(i).at(j+1).curState == active) ++occupiedNeighbors;
  118.  
  119.     return occupiedNeighbors;
  120.   }
  121.  
  122.   int countOccupiedVisible(int I, int J) {
  123.     int occupiedVisible = 0;
  124.  
  125.     // check above
  126.     for (int i = I - 1, j = J; i >= 0; --i) {
  127.       if (matrix.at(i).at(j).curState == inactive) { break; }
  128.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  129.     }
  130.     // check below
  131.     for (int i = I + 1, j = J; i < height; ++i) {
  132.       if (matrix.at(i).at(j).curState == inactive) { break; }
  133.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  134.     }
  135.  
  136.     // check right
  137.     for (int i = I, j = J + 1; j < width; ++j) {
  138.       if (matrix.at(i).at(j).curState == inactive) { break; }
  139.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  140.     }
  141.  
  142.     // check left
  143.     for (int i = I, j = J - 1; j >= 0; --j) {
  144.       if (matrix.at(i).at(j).curState == inactive) { break; }
  145.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  146.     }
  147.  
  148.     // check up-right
  149.     for (int i = I - 1, j = J + 1; i >= 0 && j < width; --i, ++j) {
  150.       if (matrix.at(i).at(j).curState == inactive) { break; }
  151.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  152.     }
  153.  
  154.     // check up-left
  155.     for (int i = I - 1, j = J - 1; i >= 0 && j >= 0; --i, --j) {
  156.       if (matrix.at(i).at(j).curState == inactive) { break; }
  157.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  158.     }
  159.  
  160.     // check down-right
  161.     for (int i = I + 1, j = J + 1; i < height && j < width; ++i, ++j) {
  162.       if (matrix.at(i).at(j).curState == inactive) { break; }
  163.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  164.     }
  165.  
  166.     // check down-left
  167.     for (int i = I + 1, j = J - 1; i < height && j >= 0; ++i, --j) {
  168.       if (matrix.at(i).at(j).curState == inactive) { break; }
  169.       if (matrix.at(i).at(j).curState == active) { ++occupiedVisible; break; }
  170.     }
  171.  
  172.     return occupiedVisible;
  173.   }
  174. };
  175.  
  176. int main() {
  177.   Automata automata(std::ifstream("input.txt", std::ios::in));
  178.  
  179.   bool viewNeighborsOnly = true;
  180.   automata.stabilize(viewNeighborsOnly);
  181.  
  182.   std::cout << "Part 1: " << automata.activeCells() << std::endl;
  183.  
  184.   automata.reset();
  185.   viewNeighborsOnly = false;
  186.   automata.stabilize(viewNeighborsOnly);
  187.  
  188.   std::cout << "Part 2: " << automata.activeCells() << std::endl;
  189.  
  190.   return 0;
  191. }
  192.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement