diff --git a/main.cc b/main.cc index 199c88f..5ce2741 100644 --- a/main.cc +++ b/main.cc @@ -57,6 +57,78 @@ namespace { int length_; ///< Side length }; + /** Structure holding the results. + */ + struct Results { + Results(int length, std::vector squares) : length_(length), squares_(std::move(squares)) { + } + + Results(Results const &other) noexcept = delete; + Results &operator=(Results const &other) noexcept = delete; + Results &operator=(Results &&other) noexcept = default; + Results(Results &&other) noexcept = default; + ~Results() noexcept = default; + + auto length() const noexcept -> int { return length_; } + + /** Output the grid. */ + auto output() const -> void { + std::string out; + out.resize(length_ * length_); + for (auto const& sq : squares_) { + prettify_sq(out, sq); + } + for (auto idx = 0; idx < length_ * length_; idx += length_) { + std::cout << std::string_view(out.data() + idx, length_) << '\n'; + } + } + + private: + auto set(std::string& s, int x, int y, char c) const noexcept -> void { + assert(x < length_); + assert(y < length_); + assert(grid_[x + y * length_] != c); + s[x + y * length_] = c; + } + + auto prettify_sq(std::string& s, Square const &sq) const noexcept -> void { + switch (sq.length()) { + case 1: set(s, sq.x(), sq.y(), '*'); + break; + case 2: set(s, sq.x(), sq.y(), '+'); + set(s, sq.x() + 1, sq.y(), '+'); + set(s, sq.x(), sq.y() + 1, '+'); + set(s, sq.x() + 1, sq.y() + 1, '+'); + break; + default: { + auto n = sq.length(); + set(s, sq.x(), sq.y(), '+'); + set(s, sq.x() + n - 1, sq.y(), '+'); + set(s, sq.x(), sq.y() + n - 1, '+'); + set(s, sq.x() + n - 1, sq.y() + n - 1, '+'); + for (int i = 1; i < n - 1; ++i) { + set(s, sq.x() + i, sq.y(), '-'); + set(s, sq.x() + i, sq.y() + n - 1, '-'); + set(s, sq.x(), sq.y() + i, '|'); + for (int j = 1; j < n - 1; ++j) { + set(s, sq.x() + j, sq.y() + i, ' '); + } + set(s, sq.x() + n - 1, sq.y() + i, '|'); + } + + int i = sq.x() + n - 1; + while (n != 0) { + set(s, --i, sq.y() + 1, '0' + (n % 10)); + n /= 10; + } + } + } + } + + int length_; + std::vector squares_; + }; + /** An N * N grid of characters. */ struct Grid { /** Construct a grid of given side-length. */ @@ -94,22 +166,6 @@ namespace { } } - auto prettify() noexcept -> void { - for (auto idx = 0; idx < grid_.size(); ++idx) { - if (grid_[idx] < 32) { - auto const pos = std::make_pair(idx % length_, idx / length_); - prettify_sq(Square(pos, grid_[idx])); - } - } - } - - /** Output the grid. */ - auto output() const -> void { - for (auto idx = 0; idx < length_ * length_; idx += length_) { - std::cout << std::string_view(grid_.data() + idx, length_) << '\n'; - } - } - /** \brief Get length of the largest square that fits at \a pos in the grid. */ auto largest_square(Pos const &pos, int n) const noexcept -> int { @@ -147,39 +203,6 @@ namespace { } private: - auto prettify_sq(Square const &sq) noexcept -> void { - switch (sq.length()) { - case 1: set(sq.x(), sq.y(), '*'); - break; - case 2: set(sq.x(), sq.y(), '+'); - set(sq.x() + 1, sq.y(), '+'); - set(sq.x(), sq.y() + 1, '+'); - set(sq.x() + 1, sq.y() + 1, '+'); - break; - default: { - auto n = sq.length(); - set(sq.x(), sq.y(), '+'); - set(sq.x() + n - 1, sq.y(), '+'); - set(sq.x(), sq.y() + n - 1, '+'); - set(sq.x() + n - 1, sq.y() + n - 1, '+'); - for (int i = 1; i < n - 1; ++i) { - set(sq.x() + i, sq.y(), '-'); - set(sq.x() + i, sq.y() + n - 1, '-'); - set(sq.x(), sq.y() + i, '|'); - for (int j = 1; j < n - 1; ++j) { - set(sq.x() + j, sq.y() + i, ' '); - } - set(sq.x() + n - 1, sq.y() + i, '|'); - } - - int i = sq.x() + n - 1; - while (n != 0) { - set(--i, sq.y() + 1, '0' + (n % 10)); - n /= 10; - } - } - } - } /** Set the grid position (x, y) to the character c. * @@ -209,7 +232,7 @@ namespace { * * Returns the grid of the solution. */ - auto find_solution(int const n) noexcept -> Grid { + auto find_solution(int const n) noexcept -> Results { /* Implementation is iterative, as opposed to recursive. * * The recursive implementation is easier to understand - but is @@ -277,8 +300,7 @@ namespace { if (x(pos) == 0 && y(pos) == grid.length()) { break; } } - grid.prettify(); - return grid; + return Results(length, sqs); } } // anon namespace