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:
25
main.cc
25
main.cc
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <string>
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
@@ -44,11 +43,11 @@ struct Grid {
|
|||||||
Grid(int length) : grid_(length * length, '.'), length_(length) {
|
Grid(int length) : grid_(length * length, '.'), length_(length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Grid(Grid const &other) = default;
|
Grid(Grid const &other) = delete;
|
||||||
|
|
||||||
Grid(Grid &&other) noexcept = default;
|
Grid(Grid &&other) noexcept = default;
|
||||||
|
|
||||||
Grid &operator=(Grid const &other) = default;
|
Grid &operator=(Grid const &other) = delete;
|
||||||
|
|
||||||
Grid &operator=(Grid &&other) noexcept = default;
|
Grid &operator=(Grid &&other) noexcept = default;
|
||||||
|
|
||||||
@@ -113,7 +112,8 @@ struct Grid {
|
|||||||
|
|
||||||
auto output() const {
|
auto output() const {
|
||||||
for (auto i = 0; i < length_; ++i) {
|
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; }
|
if (grid_[b + y(pos) * length_] != '.') { break; }
|
||||||
++b;
|
++b;
|
||||||
}
|
}
|
||||||
|
// Check that this length fits vertically as well.
|
||||||
auto len = b - x(pos);
|
auto len = b - x(pos);
|
||||||
auto ye = std::min(y(pos) + len, length_);
|
auto ye = std::min(y(pos) + len, length_);
|
||||||
return ye - y(pos);
|
return ye - y(pos);
|
||||||
@@ -146,15 +147,16 @@ struct Grid {
|
|||||||
* added.
|
* added.
|
||||||
*/
|
*/
|
||||||
auto next_pos(Pos const &pos, int n) const noexcept -> Pos {
|
auto next_pos(Pos const &pos, int n) const noexcept -> Pos {
|
||||||
const auto p = x(pos) + n + y(pos) * length_;
|
auto const b = grid_.begin() + x(pos) + n + y(pos) * length_;
|
||||||
const auto next_p = grid_.find('.', p);
|
auto const p = std::find(b, grid_.end(), '.');
|
||||||
if (next_p == std::string::npos) {
|
if (p == grid_.end()) {
|
||||||
return std::make_pair(0, length_);
|
return std::make_pair(0, length_);
|
||||||
}
|
}
|
||||||
return std::make_pair(next_p % length_, next_p / length_);
|
auto const v = p - grid_.begin();
|
||||||
|
return std::make_pair(v % length_, v / length_);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string grid_;
|
std::vector<char> grid_;
|
||||||
int length_;
|
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
|
* If we know a square of side length N will fit then we know a square of side length
|
||||||
* N - 1 will fit.
|
* 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) {
|
for (auto idx = grid.largest_square(pos, n); idx != 0; --idx) {
|
||||||
if (avail_sqs[idx] == 0) { continue; }
|
if (avail_sqs[idx] == 0) { continue; }
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user