#include #include #include "common.hpp" using std::ifstream; using std::getline; enum class ParseState { ReadCoordinates, ReadInstruction }; Sheet::Sheet(string path) { auto parsed = parse_file(path); auto coordinates = std::get<0>(parsed); auto instructions = std::get<1>(parsed); for (size_t i = 0; i < 2; i++) { auto instruction = instructions.at(i); switch (std::get<0>(instruction)) { case Axis::X: this->width = std::get<1>(instruction) * 2 + 1; break; case Axis::Y: this->height = std::get<1>(instruction) * 2 + 1; } } this->instructions = instructions; this->map.resize(width * height, false); for (auto coord : coordinates) { auto x = std::get<0>(coord); auto y = std::get<1>(coord); this->map[x + (y * this->width)] = true; } } void Sheet::fold(Axis axis, size_t pos) { switch (axis) { case Axis::X: this->fold_left(pos); break; case Axis::Y: this->fold_up(pos); break; } } void Sheet::fold_up(size_t pos) { vector top(this->width * pos, false); for (size_t row = 0; row < pos; ++row) { for (size_t col = 0; col < this->width; ++col) { size_t top_pos = col + (row * this->width); size_t bottom_pos = col + (this->map.size() - ((row + 1) * this->width)); top[top_pos] = this->map[top_pos] || this->map[bottom_pos]; } } this->height = pos; this->map = top; } void Sheet::fold_left(size_t pos) { vector left(this->height * pos, false); for (size_t row = 0; row < this->height; ++row) { for (size_t col = 0; col < pos; ++col) { size_t left_pos = col + (row * this->width); size_t right_pos = (this->width - 1 - col) + (row * this->width); left[col + (row * pos)] = this->map[left_pos] || this->map[right_pos]; } } this->width = pos; this->map = left; } void Sheet::fold_once() { auto instruction = this->instructions.at(0); this->fold(std::get<0>(instruction), std::get<1>(instruction)); } void Sheet::fold_all() { for (auto instruction : this->instructions) { this->fold(std::get<0>(instruction), std::get<1>(instruction)); } } int Sheet::count_dots() { int dots = 0; for (auto dot : this->map) { if (dot) dots++; } return dots; } void Sheet::print() { for (size_t i = 0; i < this->map.size(); ++i) { auto chr = this->map[i] ? "#" : "."; std::cout << chr << " "; if ((i + 1) % this->width == 0) { std::cout << std::endl; } } } Coordinate parse_coordinates(string str) { const string delim = ","; auto x = std::stoi(str.substr(0, str.find(delim))); str.erase(0, str.find(delim) + delim.length()); auto y = std::stoi(str); return std::make_tuple(x, y); } Instruction parse_instruction(string str) { const string delim = "="; str.erase(0, 11); auto axis = str.substr(0, str.find(delim)) == "x" ? Axis::X : Axis::Y; str.erase(0, str.find(delim) + delim.length()); auto where = std::stoi(str); return std::make_tuple(axis, where); } tuple, vector> parse_file(string path) { vector coordinates; vector instructions; ifstream file; file.open(path); auto state = ParseState::ReadCoordinates; string line; while (getline(file, line)) { switch(state) { case ParseState::ReadCoordinates: { if (line.empty()) { state = ParseState::ReadInstruction; continue; } auto coord = parse_coordinates(line); coordinates.push_back(coord); break; } case ParseState::ReadInstruction: { auto instr = parse_instruction(line); instructions.push_back(instr); break; } } } file.close(); return std::make_tuple(coordinates, instructions); }