#include <iostream>
#include <vector>
enum class Cell
{
RED, BLUE, NONE
};
class GameOfLife
{
private:
int width;
int height;
std::vector<std::vector<Cell>> grid;
void setCell(int x, int y, Cell value)
{
grid[y][x] = value;
}
Cell cellAt(int x, int y) const
{
if(x >= width)
x %= width;
if(y >= height)
y %= height;
if(x < 0)
x += width;
if(y < 0)
y += height;
return grid[y][x];
}
int countAlive(int x, int y, int& redAlive, int& blueAlive) const
{
blueAlive = 0;
redAlive = 0;
for(int j = y - 1; j <= y + 1; j++)
{
for(int i = x - 1; i <= x + 1; i++)
{
if(i == x && y == j)
continue;
if(cellAt(i, j) == Cell::RED)
redAlive++;
else if(cellAt(i, j) == Cell::BLUE)
blueAlive++;
}
}
return blueAlive + redAlive;
}
Cell findColor(Cell color, int redAlive, int blueAlive) const
{
if(color == Cell::RED)
return redAlive + 1 > blueAlive ? Cell::RED : Cell::BLUE;
if(color == Cell::BLUE)
return blueAlive + 1 > redAlive ? Cell::BLUE : Cell::RED;
throw "This cell should not be dead";
}
public:
GameOfLife(std::vector<std::vector<Cell>> grid)
{
this->grid = grid;
width = grid[0].size();
height = grid.size();
}
void advanceSimulation()
{
for(int j = 0; j < height; j++)
{
for(int i = 0; i < width; i++)
{
int redAlive, blueAlive;
int alive = countAlive(i, j, redAlive, blueAlive);
Cell cell = cellAt(i, j);
if(cell == Cell::NONE)
{
if(alive == 3)
setCell(i, j, redAlive > blueAlive ? Cell::RED : Cell::BLUE);
}
else
{
if(alive < 2 || alive > 3)
setCell(i, j, Cell::NONE);
else
setCell(i, j, findColor(cell, redAlive, blueAlive));
}
}
}
}
void print() const
{
for(const auto& row: grid)
{
for(const auto& cell: row)
{
switch(cell)
{
case Cell::RED: std::cout << '#'; break;
case Cell::BLUE: std::cout << '*'; break;
case Cell::NONE: std::cout << '.'; break;
}
}
std::cout << std::endl;
}
std::cout << std::endl;
}
};
std::ostream& operator<<(std::ostream& out, const GameOfLife& game)
{
return out;
}
int main()
{
int width, height, N;
std::cin >> width >> height >> N;
std::vector<std::vector<Cell>> grid;
grid.reserve(height);
std::string line;
getline(std::cin, line);
for(int h = 0; h < height; h++)
{
std::vector<Cell> row;
row.reserve(width);
getline(std::cin, line);
for(int w = 0; w < width; w++)
{
switch(line[w])
{
case '#': row.push_back(Cell::RED); break;
case '*': row.push_back(Cell::BLUE); break;
case '.': row.push_back(Cell::NONE); break;
}
}
grid.push_back(row);
}
GameOfLife game(grid);
game.print();
while(N--)
{
game.advanceSimulation();
game.print();
}
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoJI2luY2x1ZGUgPHZlY3Rvcj4KCgllbnVtIGNsYXNzIENlbGwKCXsKCQlSRUQsIEJMVUUsIE5PTkUKCX07CgoJY2xhc3MgR2FtZU9mTGlmZQoJewoJCXByaXZhdGU6CgkJaW50IHdpZHRoOwoJCWludCBoZWlnaHQ7CgkJc3RkOjp2ZWN0b3I8c3RkOjp2ZWN0b3I8Q2VsbD4+IGdyaWQ7CgoJCXZvaWQgc2V0Q2VsbChpbnQgeCwgaW50IHksIENlbGwgdmFsdWUpCgkJewoJCQlncmlkW3ldW3hdID0gdmFsdWU7CgkJfQoKCQlDZWxsIGNlbGxBdChpbnQgeCwgaW50IHkpIGNvbnN0CgkJewoJCQlpZih4ID49IHdpZHRoKQoJCQkJeCAlPSB3aWR0aDsKCQkJaWYoeSA+PSBoZWlnaHQpCgkJCQl5ICU9IGhlaWdodDsKCQkJaWYoeCA8IDApCgkJCQl4ICs9IHdpZHRoOwoJCQlpZih5IDwgMCkKCQkJCXkgKz0gaGVpZ2h0OwoJCQlyZXR1cm4gZ3JpZFt5XVt4XTsKCQl9CgoJCWludCBjb3VudEFsaXZlKGludCB4LCBpbnQgeSwgaW50JiByZWRBbGl2ZSwgaW50JiBibHVlQWxpdmUpIGNvbnN0CgkJewoJCQlibHVlQWxpdmUgPSAwOwoJCQlyZWRBbGl2ZSA9IDA7CgkJCWZvcihpbnQgaiA9IHkgLSAxOyBqIDw9IHkgKyAxOyBqKyspCgkJCXsKCQkJCWZvcihpbnQgaSA9IHggLSAxOyBpIDw9IHggKyAxOyBpKyspCgkJCQl7CgkJCQkJaWYoaSA9PSB4ICYmIHkgPT0gaikKCQkJCQkJY29udGludWU7CgkJCQkJaWYoY2VsbEF0KGksIGopID09IENlbGw6OlJFRCkKCQkJCQkJcmVkQWxpdmUrKzsKCQkJCQllbHNlIGlmKGNlbGxBdChpLCBqKSA9PSBDZWxsOjpCTFVFKQoJCQkJCQlibHVlQWxpdmUrKzsKCQkJCX0KCQkJfQoJCQlyZXR1cm4gYmx1ZUFsaXZlICsgcmVkQWxpdmU7CgkJfQoKCQlDZWxsIGZpbmRDb2xvcihDZWxsIGNvbG9yLCBpbnQgcmVkQWxpdmUsIGludCBibHVlQWxpdmUpIGNvbnN0CgkJewoJCQlpZihjb2xvciA9PSBDZWxsOjpSRUQpCgkJCQlyZXR1cm4gcmVkQWxpdmUgKyAxID4gYmx1ZUFsaXZlID8gQ2VsbDo6UkVEIDogQ2VsbDo6QkxVRTsKCQkJaWYoY29sb3IgPT0gQ2VsbDo6QkxVRSkKCQkJCXJldHVybiBibHVlQWxpdmUgKyAxID4gcmVkQWxpdmUgPyBDZWxsOjpCTFVFIDogQ2VsbDo6UkVEOwoJCQl0aHJvdyAiVGhpcyBjZWxsIHNob3VsZCBub3QgYmUgZGVhZCI7CgkJfQoKCQlwdWJsaWM6CgkJR2FtZU9mTGlmZShzdGQ6OnZlY3RvcjxzdGQ6OnZlY3RvcjxDZWxsPj4gZ3JpZCkKCQl7CgkJCXRoaXMtPmdyaWQgPSBncmlkOwoJCQl3aWR0aCA9IGdyaWRbMF0uc2l6ZSgpOwoJCQloZWlnaHQgPSBncmlkLnNpemUoKTsKCQl9CgoJCXZvaWQgYWR2YW5jZVNpbXVsYXRpb24oKQoJCXsKCQkJZm9yKGludCBqID0gMDsgaiA8IGhlaWdodDsgaisrKQoJCQl7CgkJCQlmb3IoaW50IGkgPSAwOyBpIDwgd2lkdGg7IGkrKykKCQkJCXsKCQkJCQlpbnQgcmVkQWxpdmUsIGJsdWVBbGl2ZTsKCQkJCQlpbnQgYWxpdmUgPSBjb3VudEFsaXZlKGksIGosIHJlZEFsaXZlLCBibHVlQWxpdmUpOwoJCQkJCUNlbGwgY2VsbCA9IGNlbGxBdChpLCBqKTsKCgkJCQkJaWYoY2VsbCA9PSBDZWxsOjpOT05FKQoJCQkJCXsKCQkJCQkJaWYoYWxpdmUgPT0gMykKCQkJCQkJCXNldENlbGwoaSwgaiwgcmVkQWxpdmUgPiBibHVlQWxpdmUgPyBDZWxsOjpSRUQgOiBDZWxsOjpCTFVFKTsKCQkJCQl9CgkJCQkJZWxzZQoJCQkJCXsKCgkJCQkJCWlmKGFsaXZlIDwgMiB8fCBhbGl2ZSA+IDMpCgkJCQkJCQlzZXRDZWxsKGksIGosIENlbGw6Ok5PTkUpOwoJCQkJCQllbHNlCgkJCQkJCQlzZXRDZWxsKGksIGosIGZpbmRDb2xvcihjZWxsLCByZWRBbGl2ZSwgYmx1ZUFsaXZlKSk7CgkJCQkJfQoJCQkJfQoJCQl9CgkJfQoKCQl2b2lkIHByaW50KCkgY29uc3QKCQl7CgkJCWZvcihjb25zdCBhdXRvJiByb3c6IGdyaWQpCgkJCXsKCQkJCWZvcihjb25zdCBhdXRvJiBjZWxsOiByb3cpCgkJCQl7CgkJCQkJc3dpdGNoKGNlbGwpCgkJCQkJewoJCQkJCQljYXNlIENlbGw6OlJFRDoJCXN0ZDo6Y291dCA8PCAnIyc7IGJyZWFrOwoJCQkJCQljYXNlIENlbGw6OkJMVUU6CXN0ZDo6Y291dCA8PCAnKic7IGJyZWFrOwoJCQkJCQljYXNlIENlbGw6Ok5PTkU6CXN0ZDo6Y291dCA8PCAnLic7IGJyZWFrOwoJCQkJCX0KCQkJCX0KCQkJCXN0ZDo6Y291dCA8PCBzdGQ6OmVuZGw7CgkJCX0KCQkJc3RkOjpjb3V0IDw8IHN0ZDo6ZW5kbDsKCQl9Cgl9OwoKCXN0ZDo6b3N0cmVhbSYgb3BlcmF0b3I8PChzdGQ6Om9zdHJlYW0mIG91dCwgY29uc3QgR2FtZU9mTGlmZSYgZ2FtZSkKCXsKCQlyZXR1cm4gb3V0OwoJfQoKCWludCBtYWluKCkKCXsKCQlpbnQgd2lkdGgsIGhlaWdodCwgTjsKCQlzdGQ6OmNpbiA+PiB3aWR0aCA+PiBoZWlnaHQgPj4gTjsKCQlzdGQ6OnZlY3RvcjxzdGQ6OnZlY3RvcjxDZWxsPj4gZ3JpZDsKCQlncmlkLnJlc2VydmUoaGVpZ2h0KTsKCQlzdGQ6OnN0cmluZyBsaW5lOwoJCWdldGxpbmUoc3RkOjpjaW4sIGxpbmUpOwoJCWZvcihpbnQgaCA9IDA7IGggPCBoZWlnaHQ7IGgrKykKCQl7CgkJCXN0ZDo6dmVjdG9yPENlbGw+IHJvdzsKCQkJcm93LnJlc2VydmUod2lkdGgpOwoJCQlnZXRsaW5lKHN0ZDo6Y2luLCBsaW5lKTsKCQkJZm9yKGludCB3ID0gMDsgdyA8IHdpZHRoOyB3KyspCgkJCXsKCQkJCXN3aXRjaChsaW5lW3ddKQoJCQkJewoJCQkJCWNhc2UgJyMnOiByb3cucHVzaF9iYWNrKENlbGw6OlJFRCk7CWJyZWFrOwoJCQkJCWNhc2UgJyonOiByb3cucHVzaF9iYWNrKENlbGw6OkJMVUUpOwlicmVhazsKCQkJCQljYXNlICcuJzogcm93LnB1c2hfYmFjayhDZWxsOjpOT05FKTsJYnJlYWs7CgkJCQl9CgkJCX0KCQkJZ3JpZC5wdXNoX2JhY2socm93KTsKCQl9CgkJR2FtZU9mTGlmZSBnYW1lKGdyaWQpOwoJCWdhbWUucHJpbnQoKTsKCQl3aGlsZShOLS0pCgkJewoJCQlnYW1lLmFkdmFuY2VTaW11bGF0aW9uKCk7CgkJCWdhbWUucHJpbnQoKTsKCQl9CgoJCXJldHVybiAwOwoJfQ==