commit 260874dfa278ba73acb805eaf53464771e84d6e5
parent 57ef6777cbec5c9f61b1fbe942e5732fb7aa68e7
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date: Tue, 2 Apr 2024 22:36:45 +0200
Add util functions and proper grid clearing on set
Diffstat:
M | main.cpp | | | 230 | ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------- |
1 file changed, 152 insertions(+), 78 deletions(-)
diff --git a/main.cpp b/main.cpp
@@ -1,107 +1,181 @@
#include <bit>
#include <bitset>
+#include <cassert>
#include <cinttypes>
+#include <format>
#include <iomanip>
#include <iostream>
-static const std::int64_t mask_field = (1 << 9) - 1;
+static constexpr const std::int64_t mask_field = (1 << 9) - 1;
+static constexpr const std::int64_t mask_value = 0x201008040201;
+
+using row_col_t = std::tuple<uint8_t, uint8_t>;
+
+std::ostream &operator<<(std::ostream &os, row_col_t rc) {
+ return os << std::format("({}, {})", std::get<0>(rc), std::get<1>(rc));
+}
+
+row_col_t row_col(const uint8_t field) { return {field / 3, field % 3}; }
+row_col_t row_col_rev(const uint8_t field) { return {2 - field % 3, field / 3}; }
+
+row_col_t row_col(const row_col_t rcr) { return {std::get<1>(rcr), 2 - std::get<0>(rcr)}; }
+row_col_t row_col_rev(const row_col_t rc) { return {2 - std::get<1>(rc), std::get<0>(rc)}; }
+
+uint8_t field(const row_col_t rc) { return 3 * std::get<0>(rc) + std::get<1>(rc); }
class Row {
-public:
- Row(std::uint64_t value = 0) : val(value) {}
- operator std::uint64_t() const { return val; }
-
- std::uint64_t get(uint8_t field) const {
- uint64_t shift = field * 9;
- return (val >> shift) & mask_field;
- }
-
- void set(uint8_t field, uint8_t value) {
- uint64_t shift = field * 9;
- val &= ~(mask_field << shift);
- val |= (1ull << value) << shift;
- }
-
- friend std::ostream &operator<<(std::ostream &os, const Row r) {
- return os << std::setfill('0') << std::setw(14) << std::hex
- << (r.val & ((1ul << 54) - 1));
- }
-
-private:
- std::uint64_t val;
+ public:
+ Row(uint64_t value = 0) : val(value) {}
+ operator uint64_t() const { return val; }
+
+ void set(uint8_t field, uint8_t value) {
+ clear(field);
+ toggle(field, value);
+ }
+
+ uint64_t get(uint8_t field) const { return (val >> 9 * field) & mask_field; }
+ uint64_t get(uint8_t field, uint8_t value) const { return (val >> 9 * field) & (1 << value); }
+
+ void toggle(uint8_t field) { val ^= mask_field << 9 * field; }
+ void clear(uint8_t field) { val &= ~(mask_field << 9 * field); }
+
+ void toggle(uint8_t field, uint8_t value) { val ^= 1ull << (9 * field + value); }
+ void clear(uint8_t field, uint8_t value) { val &= ~(1ull << (9 * field + value)); }
+
+ void toggle_all(uint8_t value) { val ^= mask_value << value; }
+ void clear_all(uint8_t value) { val &= ~(mask_value << value); }
+
+ friend std::ostream &operator<<(std::ostream &os, const Row r) {
+ return os << std::setfill('0') << std::setw(14) << std::hex << (r.val & ((1ul << 54) - 1));
+ }
+
+ private:
+ uint64_t val;
};
class Subgrid {
-public:
- Subgrid() {}
+ public:
+ Subgrid() {}
+
+ uint64_t get(row_col_t rc) const { return rows[std::get<0>(rc)].get(std::get<1>(rc)); }
+ uint64_t get_rev(row_col_t rc) const { return rows[std::get<0>(rc)].get(std::get<1>(rc) + 3); }
+
+ void set(uint8_t field, uint8_t value) {
+ assert(field < 9 && value < 9);
+
+ rows[0].clear_all(value);
+ rows[1].clear_all(value);
+ rows[2].clear_all(value);
- std::uint64_t get(uint8_t field) const {
- return rows[field / 3].get(field % 3);
- }
+ set(row_col(field), value);
+ set_rev(row_col_rev(field), value);
+ }
+
+ void clear_row(uint8_t row, uint8_t value) {
+ assert(row < 3 && value < 9);
- void set(uint8_t field, uint8_t value) {
- rows[field / 3].set(field % 3, value);
- rows[2 - field % 3].set(3 + field / 3, value);
- }
+ for (int i = 0; i < 3; i++) {
+ clear({row, i}, value);
+ clear_rev(row_col_rev({row, i}), value);
+ }
+ }
- friend std::ostream &operator<<(std::ostream &os, const Subgrid &b) {
+ void clear_col(uint8_t col, uint8_t value) {
+ assert(col < 3 && value < 9);
- for (int i = 0; i < 3; i++) {
- os << b.rows[i] << " ";
+ for (int i = 0; i < 3; i++) {
+ clear({i, col}, value);
+ clear_rev(row_col_rev({i, col}), value);
+ }
}
- return os;
- }
-private:
- Row rows[3] = {11111111, 22222222, 33333333};
+ friend std::ostream &operator<<(std::ostream &os, const Subgrid &b) {
+
+ for (int i = 0; i < 3; i++) {
+ os << b.rows[i] << " ";
+ }
+ return os;
+ }
+
+ private:
+ void set(row_col_t rc, uint8_t value) { rows[std::get<0>(rc)].set(std::get<1>(rc), value); }
+ void set_rev(row_col_t rc, uint8_t value) { rows[std::get<0>(rc)].set(std::get<1>(rc) + 3, value); }
+
+ void clear(row_col_t rc, uint8_t value) { rows[std::get<0>(rc)].clear(std::get<1>(rc), value); }
+ void clear_rev(row_col_t rc, uint8_t value) { rows[std::get<0>(rc)].clear(std::get<1>(rc) + 3, value); }
+
+ Row rows[3] = {~0, ~0, ~0};
};
class Grid {
-public:
- void set(uint8_t subgrid, uint8_t field, uint8_t value) {
- subgrids[subgrid].set(field, value);
- }
-
- void print() const {
- for (int i = 0; i < 9; i++) {
- for (int j = 0; j < 9; j++) {
- std::bitset<9> value =
- subgrids[(i / 3) * 3 + j / 3].get((i % 3) * 3 + j % 3);
- std::cout << value << " ";
- if (j % 3 == 2)
- std::cout << " ";
- }
- std::cout << std::endl;
- if (i % 3 == 2)
+ public:
+ void set(uint8_t subgrid, uint8_t field, uint8_t value) {
+ assert(subgrid < 9 && field < 9 && value < 9);
+
+ const auto [row, col] = row_col(subgrid);
+ const auto [frow, fcol] = row_col(field);
+
+ subgrids[3 * row + 0].clear_row(frow, value);
+ subgrids[3 * row + 1].clear_row(frow, value);
+ subgrids[3 * row + 2].clear_row(frow, value);
+
+ subgrids[col + 0].clear_col(fcol, value);
+ subgrids[col + 3].clear_col(fcol, value);
+ subgrids[col + 6].clear_col(fcol, value);
+
+ subgrids[subgrid].set(field, value);
+ }
+
+ void print() const {
+
+ std::cout << "Field: " << std::endl;
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 9; j++) {
+ const row_col_t subgrid = {i / 3, j / 3};
+ const row_col_t field = {i % 3, j % 3};
+ std::bitset<9> value = subgrids[::field(subgrid)].get(field);
+ std::cout << value << " ";
+ if (j % 3 == 2) std::cout << " ";
+ }
+ std::cout << std::endl;
+ if (i % 3 == 2) std::cout << std::endl;
+ }
+
std::cout << std::endl;
+
+ std::cout << "Reversed Field: " << std::endl;
+ for (int i = 0; i < 9; i++) {
+ for (int j = 0; j < 9; j++) {
+ const row_col_t subgrid = {i / 3, j / 3};
+ const row_col_t rfield = row_col_rev({i % 3, j % 3});
+ std::bitset<9> value = subgrids[::field(subgrid)].get_rev(rfield);
+ std::cout << value << " ";
+ if (j % 3 == 2) std::cout << " ";
+ }
+ std::cout << std::endl;
+ if (i % 3 == 2) std::cout << std::endl;
+ }
}
- }
- friend std::ostream &operator<<(std::ostream &os, const Grid &g) {
- for (int i = 0; i < 9; i++) {
- std::cout << g.subgrids[i] << std::endl;
+ friend std::ostream &operator<<(std::ostream &os, const Grid &g) {
+ for (int i = 0; i < 9; i++) {
+ std::cout << g.subgrids[i] << std::endl;
+ }
+ return os;
}
- return os;
- }
-private:
- Subgrid subgrids[9];
+ private:
+ Subgrid subgrids[9];
};
int main(void) {
- Grid g;
-
- g.set(0, 0, 0);
- g.set(0, 1, 1);
- g.set(0, 2, 2);
- g.set(0, 3, 3);
- g.set(0, 4, 4);
- g.set(0, 5, 5);
- g.set(0, 6, 6);
- g.set(0, 7, 7);
- g.set(0, 8, 8);
- std::cout << g << std::endl;
- g.print();
-
- return 0;
+ Grid g;
+
+ g.set(0, 0, 3);
+ g.set(4, 4, 4);
+ g.set(8, 8, 0);
+ std::cout << g << std::endl;
+ g.print();
+
+ return 0;
}