doasku

Sudoku solver
git clone git://git.dimitrijedobrota.com/doasku.git
Log | Files | Refs | README | LICENSE

commit aded653ae1e36bb63d3d9663569a5b84e930a3df
parent 373064734d5b09ee3e8181d04f6a92396fb20a65
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Tue,  9 Apr 2024 23:45:18 +0200

Cleanup code with helper functions

Diffstat:
Mmain.cpp | 136+++++++++++++++++++++++++++++++++----------------------------------------------
1 file changed, 57 insertions(+), 79 deletions(-)

diff --git a/main.cpp b/main.cpp @@ -46,6 +46,47 @@ struct row_col_t { }; class Ref { + auto get_pointing(uint16_t mask, uint16_t &seen) const { + std::vector<std::tuple<uint8_t, uint8_t>> res; + + for (uint8_t i = 0; i < 9; i++) { + const uint8_t popcnt = std::popcount(ref[i]); + if (popcnt < 2 || popcnt > 3) continue; + + if ((seen & (1 << i)) == 0) { + uint16_t cmask = mask; + for (uint8_t k = 0; k < 3; k++, cmask <<= 3) { + if (std::popcount(uint16_t(cmask & ref[i])) != popcnt) continue; + seen |= 1 << i; + res.emplace_back(k, i); + break; + } + } + } + + return res; + } + + void get_indices(uint8_t indices[9], uint16_t mask) const { + uint8_t size = 0; + while (mask) { + const uint8_t idx = std::countr_zero(mask); + indices[size++] = idx; + mask ^= 1ull << idx; + } + } + + using hidden_t = std::tuple<uint8_t, uint16_t>; + using hiddens_t = std::vector<hidden_t>; + + void get_hidden_changes(uint8_t fields[9], uint16_t mask, uint8_t n, hiddens_t &vec) const { + for (uint8_t i = 0; i < n; i++) { + const uint16_t change = value[fields[i]] & ~(value[fields[i]] & mask); + if (!change) continue; + vec.emplace_back(fields[i], change); + } + } + public: uint16_t get(uint8_t field) const { return value[field]; } uint16_t get_ref(uint8_t value) const { return ref[value]; } @@ -67,45 +108,13 @@ class Ref { } auto get_pointing_row() const { - std::vector<std::tuple<uint8_t, uint8_t>> res; - - for (uint8_t i = 0; i < 9; i++) { - const uint8_t popcnt = std::popcount(ref[i]); - if (popcnt < 2 || popcnt > 3) continue; - - if ((seen_point_row & (1 << i)) == 0) { - uint16_t row_mask = 0x7; - for (uint8_t k = 0; k < 3; k++, row_mask <<= 3) { - if (std::popcount(uint16_t(row_mask & ref[i])) != popcnt) continue; - seen_point_row |= 1 << i; - res.emplace_back(k, i); - break; - } - } - } - - return res; + static const uint16_t row_mask = 0x7; + return get_pointing(row_mask, seen_point_row); } auto get_pointing_col() const { - std::vector<std::tuple<uint8_t, uint8_t>> res; - - for (uint8_t i = 0; i < 9; i++) { - const uint8_t popcnt = std::popcount(ref[i]); - if (popcnt < 2 || popcnt > 3) continue; - - if ((seen_point_col & (1 << i)) == 0) { - uint16_t col_mask = 0x49; - for (uint8_t k = 0; k < 3; k++, col_mask <<= 3) { - if (std::popcount(uint16_t(col_mask & ref[i])) != popcnt) continue; - seen_point_col |= 1 << i; - res.emplace_back(k, i); - break; - } - } - } - - return res; + static const uint16_t col_mask = 0x49; + return get_pointing(col_mask, seen_point_col); } auto get_hidden_singles() const { @@ -120,7 +129,7 @@ class Ref { } auto get_hidden_pairs() const { - std::vector<std::tuple<uint8_t, uint16_t>> res; + hiddens_t res; for (uint8_t i = 0; i < 9; i++) { if (std::popcount(ref[i]) != 2) continue; @@ -133,21 +142,10 @@ class Ref { seen_hidden_pair |= 1ul << j; static uint8_t fields[9]; - uint8_t size = 0; - - uint16_t tval = ref[i]; - while (tval) { - const uint8_t idx = std::countr_zero(tval); - fields[size++] = idx; - tval ^= 1ull << idx; - } + get_indices(fields, ref[i]); - uint16_t mask = (1 << i) | (1 << j); - for (uint8_t i = 0; i < 2; i++) { - const uint16_t change = value[fields[i]] & ~(value[fields[i]] & mask); - if (!change) continue; - res.emplace_back(fields[i], change); - } + const uint16_t mask = (1 << i) | (1 << j); + get_hidden_changes(fields, mask, 2, res); } } @@ -155,7 +153,7 @@ class Ref { } auto get_hidden_triplets() const { - std::vector<std::tuple<uint8_t, uint16_t>> res; + hiddens_t res; for (uint8_t i = 0; i < 9; i++) { if (std::popcount(ref[i]) < 2) continue; @@ -169,7 +167,7 @@ class Ref { if (std::popcount(ref[k]) < 2) continue; if (seen_hidden_triplet & (1ul << k)) continue; - uint16_t val = ref[i] | ref[j] | ref[k]; + const uint16_t val = ref[i] | ref[j] | ref[k]; if (std::popcount(val) != 3) continue; seen_hidden_triplet |= 1ul << i; @@ -177,21 +175,10 @@ class Ref { seen_hidden_triplet |= 1ul << k; static uint8_t fields[9]; - uint8_t size = 0; - - uint16_t tval = val; - while (tval) { - const uint8_t idx = std::countr_zero(tval); - fields[size++] = idx; - tval ^= 1ull << idx; - } + get_indices(fields, val); uint16_t mask = (1 << i) | (1 << j) | (1 << k); - for (uint8_t i = 0; i < 3; i++) { - const uint16_t change = value[fields[i]] & ~(value[fields[i]] & mask); - if (!change) continue; - res.emplace_back(fields[i], change); - } + get_hidden_changes(fields, mask, 3, res); } } } @@ -227,21 +214,10 @@ class Ref { seen_hidden_quads |= 1ul << l; static uint8_t fields[9]; - uint8_t size = 0; - - uint16_t tval = val; - while (tval) { - const uint8_t idx = std::countr_zero(tval); - fields[size++] = idx; - tval ^= 1ull << idx; - } + get_indices(fields, val); uint16_t mask = (1 << i) | (1 << j) | (1 << k) | (1 << l); - for (uint8_t i = 0; i < 4; i++) { - const uint16_t change = value[fields[i]] & ~(value[fields[i]] & mask); - if (!change) continue; - res.emplace_back(fields[i], change); - } + get_hidden_changes(fields, mask, 4, res); } } } @@ -323,6 +299,7 @@ class Ref { auto get_naked_quads() const { std::vector<std::tuple<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t>> res; + for (uint8_t i = 0; i < 9; i++) { if (this->res[i]) continue; if (seen_naked_quad & (1ul << i)) continue; @@ -362,6 +339,7 @@ class Ref { private: uint16_t value[9] = {mask_field, mask_field, mask_field, mask_field, mask_field, mask_field, mask_field, mask_field, mask_field}; + uint16_t ref[9] = {mask_field, mask_field, mask_field, mask_field, mask_field, mask_field, mask_field, mask_field, mask_field};