From e557933590496a3f7b80718292c72174f4ff23a8 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Thu, 4 Sep 2025 10:53:20 +0200 Subject: [PATCH] [1/n]: Refactor x() & y() calls on position The goal of this sequence of patches is to end up representing a position as a single integer index into the grid instead of an (x, y) pair. I believe this will have better performance. First step move all calls of x(), y() into calls on methods of Results & Grid as in the future these will need to use the length of the grid. --- main.cc | 79 +++++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/main.cc b/main.cc index 2ee0478..64e5ac8 100644 --- a/main.cc +++ b/main.cc @@ -19,12 +19,6 @@ namespace { /** (x, y) pair storing a position. */ using Pos = std::pair; - /** Get x co-ordinate from position */ - auto x(Pos const &p) noexcept -> size_t { return p.first; } - - /** Get y co-ordinate from position */ - auto y(Pos const &p) noexcept -> size_t { return p.second; } - /** A square - consisting of position of closest corner to origin, and side-length. */ struct Square { @@ -46,10 +40,7 @@ namespace { ~Square() noexcept = default; /** Get x co-ordinate of closest corner to origin. */ - auto x() const noexcept -> size_t { return ::x(pos_); } - - /** Get y co-ordinate of closest corner to origin. */ - auto y() const noexcept -> size_t { return ::y(pos_); } + auto pos() const noexcept -> Pos { return pos_; } /** Get side length. */ auto length() const noexcept -> size_t { return length_; } @@ -75,8 +66,7 @@ namespace { /** Output the grid. */ auto output() const -> void { - std::string out; - out.resize(length_ * length_); + std::string out(length_ * length_, '.'); for (auto const& sq : squares_) { prettify_sq(out, sq); } @@ -93,34 +83,37 @@ namespace { s[x + y * length_] = c; } + static auto sq_x(Square const& sq) noexcept -> size_t { return sq.pos().first; } + static auto sq_y(Square const& sq) noexcept -> size_t { return sq.pos().second; } + auto prettify_sq(std::string& s, Square const &sq) const noexcept -> void { switch (sq.length()) { - case 1: set(s, sq.x(), sq.y(), '*'); + case 1: set(s, sq_x(sq), sq_y(sq), '*'); 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, '+'); + case 2: set(s, sq_x(sq), sq_y(sq), '+'); + set(s, sq_x(sq) + 1, sq_y(sq), '+'); + set(s, sq_x(sq), sq_y(sq) + 1, '+'); + set(s, sq_x(sq) + 1, sq_y(sq) + 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, '+'); + set(s, sq_x(sq), sq_y(sq), '+'); + set(s, sq_x(sq) + n - 1, sq_y(sq), '+'); + set(s, sq_x(sq), sq_y(sq) + n - 1, '+'); + set(s, sq_x(sq) + n - 1, sq_y(sq) + n - 1, '+'); 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, '|'); + set(s, sq_x(sq) + i,sq_y(sq), '-'); + set(s, sq_x(sq) + i, sq_y(sq) + n - 1, '-'); + set(s, sq_x(sq), sq_y(sq) + i, '|'); for (size_t j = 1; j < n - 1; ++j) { - set(s, sq.x() + j, sq.y() + i, ' '); + set(s, sq_x(sq) + j, sq_y(sq) + i, ' '); } - set(s, sq.x() + n - 1, sq.y() + i, '|'); + set(s, sq_x(sq) + n - 1, sq_y(sq) + i, '|'); } - size_t i = sq.x() + n - 1; + size_t i = sq_x(sq) + n - 1; while (n != 0) { - set(s, --i, sq.y() + 1, '0' + (n % 10)); + set(s, --i, sq_y(sq) + 1, '0' + (n % 10)); n /= 10; } } @@ -153,10 +146,13 @@ namespace { /** Get grid length */ auto length() const noexcept -> size_t { return length_; } + auto pos_x(Pos const& pos) const noexcept -> size_t { return pos.first; } + auto pos_y(Pos const& pos) const noexcept -> size_t { return pos.second; } + /** 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) { + for (auto i = pos_x(sq.pos()); i < pos_x(sq.pos()) + sq.length(); ++i) { + for (auto j = pos_y(sq.pos()); j < pos_y(sq.pos()) + sq.length(); ++j) { set(i, j, filled); } } @@ -164,8 +160,8 @@ namespace { /** Clear a square from the grid. */ auto clear(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) { + for (auto i = pos_x(sq.pos()); i < pos_x(sq.pos()) + sq.length(); ++i) { + for (auto j = pos_y(sq.pos()); j < pos_y(sq.pos()) + sq.length(); ++j) { set(i, j, empty); } } @@ -184,31 +180,30 @@ namespace { * This means we only need to look for the first non-clear position along the * current row. */ - auto b = x(pos); + auto b = pos_x(pos); // Make sure we don't go looking in the next row. - auto e = std::min(x(pos) + n, length_); + auto e = std::min(pos_x(pos) + n, length_); while (b < e) { - if (grid_[b + y(pos) * length_] != empty) { break; } + if (grid_[b + pos_y(pos) * length_] != empty) { break; } ++b; } // Check that this length fits vertically as well. - auto len = b - x(pos); - auto ye = std::min(y(pos) + len, length_); - return ye - y(pos); + auto len = b - pos_x(pos); + auto ye = std::min(pos_y(pos) + len, length_); + return ye - pos_y(pos); } /** Get the next position to check. n is the size of the square we just * added. */ 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 b = grid_.begin() + pos_x(pos) + n + pos_y(pos) * length_; auto const p = std::find(b, grid_.end(), empty); auto const v = p - grid_.begin(); return std::make_pair(v % length_, v / length_); } private: - /** Set the grid position (x, y) to the character c. * * It is an error if (x, y) is already set to c - as that means we have overlapping @@ -283,7 +278,7 @@ namespace { sqs.pop_back(); grid.clear(sq); ++avail_sqs[sq.length()]; - pos = std::make_pair(sq.x(), sq.y()); + pos = sq.pos(); idx = sq.length() - 1; continue; } @@ -303,7 +298,7 @@ namespace { idx = grid.largest_square(pos, n); // Have we reached the end? If so success! - if (x(pos) == 0 && y(pos) == grid.length()) { break; } + if (grid.pos_x(pos) == 0 && grid.pos_y(pos) == grid.length()) { break; } } return Results(length, sqs);