advent_of_code_2021/13/main.cpp
2021-12-13 21:48:02 +01:00

173 lines
4.2 KiB
C++

#include <algorithm>
#include <deque>
#include <fstream>
#include <iostream>
#include <sstream>
#include <unordered_map>
#include <unordered_set>
#include <vector>
using Folds = std::vector<std::pair<bool, size_t>>;
class Paper {
public:
Paper() = default;
~Paper() = default;
void addPoint(size_t x, size_t y) {
bool resizeX = false;
if (y >= _dots.size()) {
_dots.resize(y + 1);
_height = y + 1;
resizeX = true;
}
if (resizeX || x >= _dots[0].size()) {
auto newX = x >= _width ? x + 1 : _width;
for (auto &line : _dots) {
line.resize(newX);
}
_width = newX;
}
_dots[y][x] = true;
}
void foldY(size_t y) {
for (size_t i = 1; i < _height - y; i++) {
for (size_t j = 0; j < _width; j++) {
if (_dots[y + i][j]) {
_dots[y - i][j] = true;
}
}
}
_height = y;
}
void foldX(size_t x) {
for (size_t i = 1; i < _width - x; i++) {
for (size_t j = 0; j < _height; j++) {
if (_dots[j][x + i]) {
_dots[j][x - i] = true;
}
}
}
_width = x;
}
void printPaper() {
for (size_t i = 0; i < _height; i++) {
for (size_t j = 0; j < _width; j++) {
std::cout << (_dots[i][j] ? '#' : ' ');
}
std::cout << std::endl;
}
std::cout << std::endl;
}
size_t getDots() {
size_t dots = 0;
for (size_t i = 0; i < _height; i++) {
for (size_t j = 0; j < _width; j++) {
if (_dots[i][j]) {
dots++;
}
}
}
return dots;
}
private:
std::vector<std::vector<bool>> _dots{};
size_t _width;
size_t _height;
};
std::pair<Paper, Folds> getPaperAndFolds(const std::string &file_name) {
Paper paper{};
Folds folds{};
std::ifstream file(file_name);
std::string str;
bool isFold = false;
while (std::getline(file, str)) {
if (str.empty()) {
isFold = true;
continue;
}
std::stringstream ss(str);
if (!isFold) {
size_t x, y;
char tmp;
ss >> x;
ss >> tmp;
ss >> y;
paper.addPoint(x, y);
} else {
std::string tmp;
char tmp_char;
bool isX = false;
size_t tmp_num;
ss >> tmp;
ss >> tmp;
ss >> tmp_char;
if (tmp_char == 'x') {
isX = true;
}
ss >> tmp_char;
ss >> tmp_num;
folds.emplace_back(isX, tmp_num);
}
}
return { paper, folds };
}
uint64_t part1(Paper &paper, Folds &folds, bool print) {
if (print) {
paper.printPaper();
}
if (folds[0].first) {
paper.foldX(folds[0].second);
} else {
paper.foldY(folds[0].second);
}
if (print) {
std::cout << "-----------" << std::endl;
paper.printPaper();
}
return paper.getDots();
}
uint64_t part2(Paper &paper, Folds &folds, bool print) {
for (size_t i = 1; i < folds.size(); i++) {
if (folds[i].first) {
paper.foldX(folds[i].second);
} else {
paper.foldY(folds[i].second);
}
if (print) {
std::cout << "-----------" << std::endl;
paper.printPaper();
}
}
return paper.getDots();
}
int main(int argc, char **argv) {
if (argc < 2) {
std::cerr << "You must provide input file!" << std::endl;
return 1;
}
auto paper_and_folds = getPaperAndFolds(argv[1]);
auto &paper = paper_and_folds.first;
auto &folds = paper_and_folds.second;
std::cout << "There are \033[91;1m" << std::endl
<< part1(paper, folds, argc > 2)
<< "\033[0m dots after the first fold." << std::endl;
part2(paper, folds, argc > 2);
std::cout << "The resulting code is:" << std::endl << "\033[91;1m";
paper.printPaper();
std::cout << "\033[0m" << std::flush;
return 0;
}