diff --git a/main.cc b/main.cc index 5ce2741..2ee0478 100644 --- a/main.cc +++ b/main.cc @@ -13,15 +13,17 @@ #include #include +using size_t = std::size_t; + namespace { /** (x, y) pair storing a position. */ - using Pos = std::pair; + using Pos = std::pair; /** Get x co-ordinate from position */ - auto x(Pos const &p) noexcept -> int { return p.first; } + auto x(Pos const &p) noexcept -> size_t { return p.first; } /** Get y co-ordinate from position */ - auto y(Pos const &p) noexcept -> int { return p.second; } + auto y(Pos const &p) noexcept -> size_t { return p.second; } /** A square - consisting of position of closest corner to origin, and side-length. */ @@ -30,7 +32,7 @@ namespace { * \param pos Position of closest corner to origin * \param length Side length. */ - Square(Pos const &pos, int const length) noexcept : pos_(pos), length_(length) { + Square(Pos const &pos, size_t const length) noexcept : pos_(pos), length_(length) { } Square(Square const &other) noexcept = default; @@ -44,23 +46,23 @@ namespace { ~Square() noexcept = default; /** Get x co-ordinate of closest corner to origin. */ - auto x() const noexcept -> int { return ::x(pos_); } + auto x() const noexcept -> size_t { return ::x(pos_); } /** Get y co-ordinate of closest corner to origin. */ - auto y() const noexcept -> int { return ::y(pos_); } + auto y() const noexcept -> size_t { return ::y(pos_); } /** Get side length. */ - auto length() const noexcept -> int { return length_; } + auto length() const noexcept -> size_t { return length_; } private: Pos pos_; ///< Position of corner closest to origin - int length_; ///< Side length + size_t length_; ///< Side length }; /** Structure holding the results. */ struct Results { - Results(int length, std::vector squares) : length_(length), squares_(std::move(squares)) { + Results(size_t length, std::vector squares) : length_(length), squares_(std::move(squares)) { } Results(Results const &other) noexcept = delete; @@ -69,7 +71,7 @@ namespace { Results(Results &&other) noexcept = default; ~Results() noexcept = default; - auto length() const noexcept -> int { return length_; } + auto length() const noexcept -> size_t { return length_; } /** Output the grid. */ auto output() const -> void { @@ -78,13 +80,13 @@ namespace { for (auto const& sq : squares_) { prettify_sq(out, sq); } - for (auto idx = 0; idx < length_ * length_; idx += length_) { + for (size_t 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 { + auto set(std::string& s, size_t x, size_t y, char c) const noexcept -> void { assert(x < length_); assert(y < length_); assert(grid_[x + y * length_] != c); @@ -106,17 +108,17 @@ namespace { 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) { + for (size_t 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) { + for (size_t 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; + size_t i = sq.x() + n - 1; while (n != 0) { set(s, --i, sq.y() + 1, '0' + (n % 10)); n /= 10; @@ -125,14 +127,17 @@ namespace { } } - int length_; + size_t length_; std::vector squares_; }; /** An N * N grid of characters. */ struct Grid { + // Type to use for the grid contents + using T = std::int_fast64_t; + /** Construct a grid of given side-length. */ - Grid(int length) : grid_(length * length, empty), length_(length) { + Grid(size_t length) : grid_(length * length, empty), length_(length) { } Grid(Grid const &other) = delete; @@ -146,13 +151,13 @@ namespace { ~Grid() noexcept = default; /** Get grid length */ - auto length() const noexcept -> int { return length_; } + auto length() const noexcept -> size_t { return length_; } /** Add a square to the grid. */ auto add(Square const &sq) noexcept -> void { for (auto i = sq.x(); i < sq.x() + sq.length(); ++i) { for (auto j = sq.y(); j < sq.y() + sq.length(); ++j) { - set(i, j, sq.length()); + set(i, j, filled); } } } @@ -168,7 +173,7 @@ namespace { /** \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 { + auto largest_square(Pos const &pos, size_t n) const noexcept -> size_t { assert(x(pos) < length_); assert(y(pos) < length_); @@ -183,7 +188,7 @@ namespace { // Make sure we don't go looking in the next row. auto e = std::min(x(pos) + n, length_); while (b < e) { - if (grid_[b + y(pos) * length_] != '.') { break; } + if (grid_[b + y(pos) * length_] != empty) { break; } ++b; } // Check that this length fits vertically as well. @@ -195,7 +200,7 @@ namespace { /** Get the next position to check. n is the size of the square we just * added. */ - auto next_pos(Pos const &pos, int n) const noexcept -> Pos { + auto next_pos(Pos const &pos, size_t n) const noexcept -> Pos { auto const b = grid_.begin() + x(pos) + n + y(pos) * length_; auto const p = std::find(b, grid_.end(), empty); auto const v = p - grid_.begin(); @@ -209,30 +214,31 @@ namespace { * It is an error if (x, y) is already set to c - as that means we have overlapping * squares. */ - auto set(int x, int y, char c) noexcept -> void { + auto set(size_t x, size_t y, T c) noexcept -> void { assert(x < length_); assert(y < length_); assert(grid_[x + y * length_] != c); grid_[x + y * length_] = c; } - std::vector grid_; ///< The grid - int length_; ///< Side length + std::vector grid_; ///< The grid + size_t length_; ///< Side length - static constexpr char empty = '.'; ///< Character used for an empty cell. + static constexpr char empty = 0; ///< Character used for an empty cell. + static constexpr char filled = 1; ///< Character used for a filled cell, }; /** Get the n'th triangular number. */ - auto triangle_num(int n) noexcept -> int { return (n * (n + 1)) / 2; } + auto triangle_num(size_t n) noexcept -> size_t { return (n * (n + 1)) / 2; } /** Vector used to identify the available squares. */ - using Avail = std::vector; + using Avail = std::vector; /** Find a solution to the \a n th Partridge problem. * * Returns the grid of the solution. */ - auto find_solution(int const n) noexcept -> Results { + auto find_solution(size_t const n) noexcept -> Results { /* Implementation is iterative, as opposed to recursive. * * The recursive implementation is easier to understand - but is @@ -262,7 +268,7 @@ namespace { // Start at the origin with a square of longest side length. Pos pos{0, 0}; - int idx = n; + size_t idx = n; while (true) { /* If the idx is 0 we've looked at all possible square lengths for this @@ -305,7 +311,7 @@ namespace { } // anon namespace int main(int argc, char **argv) { - auto n = (argc == 1) ? 8 : atoi(argv[1]); + auto n = (argc == 1) ? 8 : std::atol(argv[1]); auto grid = find_solution(n); std::cout << "Partridge problem " << n << " side length " << grid.length() << '\n'; grid.output();