[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.
This commit is contained in:
79
main.cc
79
main.cc
@@ -19,12 +19,6 @@ namespace {
|
|||||||
/** (x, y) pair storing a position. */
|
/** (x, y) pair storing a position. */
|
||||||
using Pos = std::pair<size_t, size_t>;
|
using Pos = std::pair<size_t, size_t>;
|
||||||
|
|
||||||
/** 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.
|
/** A square - consisting of position of closest corner to origin, and side-length.
|
||||||
*/
|
*/
|
||||||
struct Square {
|
struct Square {
|
||||||
@@ -46,10 +40,7 @@ namespace {
|
|||||||
~Square() noexcept = default;
|
~Square() noexcept = default;
|
||||||
|
|
||||||
/** Get x co-ordinate of closest corner to origin. */
|
/** Get x co-ordinate of closest corner to origin. */
|
||||||
auto x() const noexcept -> size_t { return ::x(pos_); }
|
auto pos() const noexcept -> Pos { return pos_; }
|
||||||
|
|
||||||
/** Get y co-ordinate of closest corner to origin. */
|
|
||||||
auto y() const noexcept -> size_t { return ::y(pos_); }
|
|
||||||
|
|
||||||
/** Get side length. */
|
/** Get side length. */
|
||||||
auto length() const noexcept -> size_t { return length_; }
|
auto length() const noexcept -> size_t { return length_; }
|
||||||
@@ -75,8 +66,7 @@ namespace {
|
|||||||
|
|
||||||
/** Output the grid. */
|
/** Output the grid. */
|
||||||
auto output() const -> void {
|
auto output() const -> void {
|
||||||
std::string out;
|
std::string out(length_ * length_, '.');
|
||||||
out.resize(length_ * length_);
|
|
||||||
for (auto const& sq : squares_) {
|
for (auto const& sq : squares_) {
|
||||||
prettify_sq(out, sq);
|
prettify_sq(out, sq);
|
||||||
}
|
}
|
||||||
@@ -93,34 +83,37 @@ namespace {
|
|||||||
s[x + y * length_] = c;
|
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 {
|
auto prettify_sq(std::string& s, Square const &sq) const noexcept -> void {
|
||||||
switch (sq.length()) {
|
switch (sq.length()) {
|
||||||
case 1: set(s, sq.x(), sq.y(), '*');
|
case 1: set(s, sq_x(sq), sq_y(sq), '*');
|
||||||
break;
|
break;
|
||||||
case 2: set(s, sq.x(), sq.y(), '+');
|
case 2: set(s, sq_x(sq), sq_y(sq), '+');
|
||||||
set(s, sq.x() + 1, sq.y(), '+');
|
set(s, sq_x(sq) + 1, sq_y(sq), '+');
|
||||||
set(s, sq.x(), sq.y() + 1, '+');
|
set(s, sq_x(sq), sq_y(sq) + 1, '+');
|
||||||
set(s, sq.x() + 1, sq.y() + 1, '+');
|
set(s, sq_x(sq) + 1, sq_y(sq) + 1, '+');
|
||||||
break;
|
break;
|
||||||
default: {
|
default: {
|
||||||
auto n = sq.length();
|
auto n = sq.length();
|
||||||
set(s, sq.x(), sq.y(), '+');
|
set(s, sq_x(sq), sq_y(sq), '+');
|
||||||
set(s, sq.x() + n - 1, sq.y(), '+');
|
set(s, sq_x(sq) + n - 1, sq_y(sq), '+');
|
||||||
set(s, sq.x(), sq.y() + n - 1, '+');
|
set(s, sq_x(sq), sq_y(sq) + n - 1, '+');
|
||||||
set(s, sq.x() + n - 1, sq.y() + n - 1, '+');
|
set(s, sq_x(sq) + n - 1, sq_y(sq) + n - 1, '+');
|
||||||
for (size_t 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(sq) + i,sq_y(sq), '-');
|
||||||
set(s, sq.x() + i, sq.y() + n - 1, '-');
|
set(s, sq_x(sq) + i, sq_y(sq) + n - 1, '-');
|
||||||
set(s, sq.x(), sq.y() + i, '|');
|
set(s, sq_x(sq), sq_y(sq) + i, '|');
|
||||||
for (size_t 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(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) {
|
while (n != 0) {
|
||||||
set(s, --i, sq.y() + 1, '0' + (n % 10));
|
set(s, --i, sq_y(sq) + 1, '0' + (n % 10));
|
||||||
n /= 10;
|
n /= 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,10 +146,13 @@ namespace {
|
|||||||
/** Get grid length */
|
/** Get grid length */
|
||||||
auto length() const noexcept -> size_t { return 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. */
|
/** Add a square to the grid. */
|
||||||
auto add(Square const &sq) noexcept -> void {
|
auto add(Square const &sq) noexcept -> void {
|
||||||
for (auto i = sq.x(); i < sq.x() + sq.length(); ++i) {
|
for (auto i = pos_x(sq.pos()); i < pos_x(sq.pos()) + sq.length(); ++i) {
|
||||||
for (auto j = sq.y(); j < sq.y() + sq.length(); ++j) {
|
for (auto j = pos_y(sq.pos()); j < pos_y(sq.pos()) + sq.length(); ++j) {
|
||||||
set(i, j, filled);
|
set(i, j, filled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -164,8 +160,8 @@ namespace {
|
|||||||
|
|
||||||
/** Clear a square from the grid. */
|
/** Clear a square from the grid. */
|
||||||
auto clear(Square const &sq) noexcept -> void {
|
auto clear(Square const &sq) noexcept -> void {
|
||||||
for (auto i = sq.x(); i < sq.x() + sq.length(); ++i) {
|
for (auto i = pos_x(sq.pos()); i < pos_x(sq.pos()) + sq.length(); ++i) {
|
||||||
for (auto j = sq.y(); j < sq.y() + sq.length(); ++j) {
|
for (auto j = pos_y(sq.pos()); j < pos_y(sq.pos()) + sq.length(); ++j) {
|
||||||
set(i, j, empty);
|
set(i, j, empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -184,31 +180,30 @@ namespace {
|
|||||||
* This means we only need to look for the first non-clear position along the
|
* This means we only need to look for the first non-clear position along the
|
||||||
* current row.
|
* current row.
|
||||||
*/
|
*/
|
||||||
auto b = x(pos);
|
auto b = pos_x(pos);
|
||||||
// Make sure we don't go looking in the next row.
|
// 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) {
|
while (b < e) {
|
||||||
if (grid_[b + y(pos) * length_] != empty) { break; }
|
if (grid_[b + pos_y(pos) * length_] != empty) { break; }
|
||||||
++b;
|
++b;
|
||||||
}
|
}
|
||||||
// Check that this length fits vertically as well.
|
// Check that this length fits vertically as well.
|
||||||
auto len = b - x(pos);
|
auto len = b - pos_x(pos);
|
||||||
auto ye = std::min(y(pos) + len, length_);
|
auto ye = std::min(pos_y(pos) + len, length_);
|
||||||
return ye - y(pos);
|
return ye - pos_y(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get the next position to check. n is the size of the square we just
|
/** Get the next position to check. n is the size of the square we just
|
||||||
* added.
|
* added.
|
||||||
*/
|
*/
|
||||||
auto next_pos(Pos const &pos, size_t 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 b = grid_.begin() + pos_x(pos) + n + pos_y(pos) * length_;
|
||||||
auto const p = std::find(b, grid_.end(), empty);
|
auto const p = std::find(b, grid_.end(), empty);
|
||||||
auto const v = p - grid_.begin();
|
auto const v = p - grid_.begin();
|
||||||
return std::make_pair(v % length_, v / length_);
|
return std::make_pair(v % length_, v / length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Set the grid position (x, y) to the character c.
|
/** 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
|
* 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();
|
sqs.pop_back();
|
||||||
grid.clear(sq);
|
grid.clear(sq);
|
||||||
++avail_sqs[sq.length()];
|
++avail_sqs[sq.length()];
|
||||||
pos = std::make_pair(sq.x(), sq.y());
|
pos = sq.pos();
|
||||||
idx = sq.length() - 1;
|
idx = sq.length() - 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -303,7 +298,7 @@ namespace {
|
|||||||
idx = grid.largest_square(pos, n);
|
idx = grid.largest_square(pos, n);
|
||||||
|
|
||||||
// Have we reached the end? If so success!
|
// 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);
|
return Results(length, sqs);
|
||||||
|
|||||||
Reference in New Issue
Block a user