Change Grid to use vector not string.

This is another optimisation, as it improves memory layout and we are
not using a reference counted string.

On a M1 Macbook Air this brings runtime for solving the 9 cell down to
under 3m30s.  Which is about a 15% performance improvement.
This commit is contained in:
2025-09-01 11:42:07 +02:00
parent 355c4211aa
commit e865b2a567

25
main.cc
View File

@@ -4,7 +4,6 @@
#include <cassert>
#include <utility>
#include <string>
#include <string_view>
#include <vector>
#include <iostream>
@@ -44,11 +43,11 @@ struct Grid {
Grid(int length) : grid_(length * length, '.'), length_(length) {
}
Grid(Grid const &other) = default;
Grid(Grid const &other) = delete;
Grid(Grid &&other) noexcept = default;
Grid &operator=(Grid const &other) = default;
Grid &operator=(Grid const &other) = delete;
Grid &operator=(Grid &&other) noexcept = default;
@@ -113,7 +112,8 @@ struct Grid {
auto output() const {
for (auto i = 0; i < length_; ++i) {
std::cout << grid_.substr(i * length_, length_) << '\n';
std::cout <<
std::string_view(grid_.data() + i * length_, length_) << '\n';
}
}
@@ -137,6 +137,7 @@ struct Grid {
if (grid_[b + y(pos) * length_] != '.') { 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);
@@ -146,15 +147,16 @@ struct Grid {
* added.
*/
auto next_pos(Pos const &pos, int n) const noexcept -> Pos {
const auto p = x(pos) + n + y(pos) * length_;
const auto next_p = grid_.find('.', p);
if (next_p == std::string::npos) {
return std::make_pair(0, length_);
}
return std::make_pair(next_p % length_, next_p / length_);
auto const b = grid_.begin() + x(pos) + n + y(pos) * length_;
auto const p = std::find(b, grid_.end(), '.');
if (p == grid_.end()) {
return std::make_pair(0, length_);
}
auto const v = p - grid_.begin();
return std::make_pair(v % length_, v / length_);
}
std::string grid_;
std::vector<char> grid_;
int length_;
};
@@ -174,6 +176,7 @@ auto find_solution_impl(Grid &grid, int n, Pos const &pos, Avail &avail_sqs) ->
* If we know a square of side length N will fit then we know a square of side length
* N - 1 will fit.
*/
assert(x(pos) + grid.largest_square(pos, n) <= grid.length());
for (auto idx = grid.largest_square(pos, n); idx != 0; --idx) {
if (avail_sqs[idx] == 0) { continue; }