doasku

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

commit f8fc7a0c1b8f2edfdb7259eec445c4244dedcf5b
parent 4bd367d95546d5af024d7a6cce8b631ae75cb53a
Author: Dimitrije Dobrota <mail@dimitrijedobrota.com>
Date:   Thu,  4 Apr 2024 21:46:25 +0200

Big code cleanup

Diffstat:
Mmain.cpp | 156+++++++++++++++++++++++++++++++++++--------------------------------------------
1 file changed, 69 insertions(+), 87 deletions(-)

diff --git a/main.cpp b/main.cpp @@ -24,6 +24,7 @@ struct row_col_t { row_col_t(row_col_rt rc); explicit operator row_col_rt() const; + operator uint8_t() const { return 3 * row + col; } row_col_t absolute(row_col_t rc) { return {uint8_t(row * 3 + rc.row), uint8_t(col * 3 + rc.col)}; } @@ -51,16 +52,14 @@ struct row_col_rt { row_col_t::row_col_t(row_col_rt rc) : row(rc.col), col(2 - rc.row) {} row_col_rt::row_col_rt(row_col_t rc) : row(2 - rc.col), col(rc.row) {} -uint8_t field(row_col_t rc) { return 3 * rc.row + rc.col; } - class Ref { public: uint16_t get(uint8_t value) const { return ref[value]; } - void clear(uint8_t value) { ref[value] = 0; } + void zero(uint8_t value) { ref[value] = 0; } - void remove(uint8_t field, uint8_t value) { ref[value] &= ~(1 << field); } - void remove(uint8_t field) { + void clear(uint8_t field, uint8_t value) { ref[value] &= ~(1 << field); } + void clear(uint8_t field) { for (uint8_t i = 0; i < 9; i++) { ref[i] &= ~(1 << field); } @@ -103,8 +102,6 @@ class Row { void toggle_all(uint8_t value) { val ^= mask_value << value; } void clear_all(uint8_t value) { val &= ~(mask_value << value); } - void mask(uint8_t field, uint16_t mask) { val &= ~(uint64_t(mask) << 9 * field); } - friend std::ostream &operator<<(std::ostream &os, Row r) { for (int i = 0; i < 6; i++) { os << std::bitset<9>(r.get(i)) << " "; @@ -130,7 +127,7 @@ class Subgrid { return 1 + std::countr_zero(get(rc)); } - bool is_finished(row_col_t rc) const { return finished & (1 << ::field(rc)); } + bool is_finished(row_col_t rc) const { return finished & (1 << rc); } bool is_finished() const { return finished == (1 << 9) - 1; } void set(row_col_t rc, uint8_t value) { @@ -143,47 +140,19 @@ class Subgrid { _set(row_col_rt(rc), value); _set(rc, value); - const uint8_t field = ::field(rc); - - ref.clear(value); - ref.remove(field); - - finished |= 1 << field; - } - - void clear_row(uint8_t row, uint8_t value) { - assert(row < 3 && value < 9); + ref.zero(value); + ref.clear(rc); - for (uint8_t i = 0; i < 3; i++) { - const row_col_t rc = {row, i}; - _clear(row_col_rt(rc), value); - _clear(rc, value); - - ref.remove(::field(rc), value); - } + finished |= 1 << rc; } - void clear_col(uint8_t col, uint8_t value) { - assert(col < 3 && value < 9); - - for (uint8_t i = 0; i < 3; i++) { - const row_col_t rc = {i, col}; - _clear(row_col_rt(rc), value); - _clear(rc, value); - - ref.remove(::field(rc), value); - } - } + void clear(row_col_t rc, uint8_t value) { + _clear(row_col_rt(rc), value); + _clear(rc, value); - void mask(row_col_t rc, uint16_t mask) { - _mask(row_col_rt(rc), mask); - _mask(rc, mask); + ref.clear(rc, value); } - void ref_clear(row_col_t rc, uint8_t value) { ref.clear(value); } - void ref_remove(row_col_t rc, uint8_t value) { ref.remove(::field(rc), value); } - void ref_remove(row_col_t rc) { ref.remove(::field(rc)); } - changes_t get_lone() const { if (is_finished()) return {}; return ref.get_lone(); @@ -290,7 +259,7 @@ class Subgrid { os << std::endl << "Refs:" << std::endl; for (uint8_t i = 0; i < 3; i++) { for (uint8_t j = 0; j < 3; j++) { - std::cout << std::bitset<9>(s.get_ref(::field({i, j}))) << " "; + std::cout << std::bitset<9>(s.get_ref(row_col_t{i, j})) << " "; } std::cout << std::endl; } @@ -305,9 +274,6 @@ class Subgrid { void _clear(row_col_t rc, uint8_t value) { rows[rc.row].clear(rc.col, value); } void _clear(row_col_rt rcr, uint8_t value) { rows[rcr.row].clear(rcr.col + 3, value); } - void _mask(row_col_t rc, uint8_t value) { rows[rc.row].mask(rc.col, value); } - void _mask(row_col_rt rcr, uint8_t value) { rows[rcr.row].mask(rcr.col + 3, value); } - Row rows[3] = {~0, ~0, ~0}; Ref ref; @@ -332,34 +298,20 @@ class Grid { const auto ab = subgrid.absolute(field); - subgrids[3 * subgrid.row + 0].clear_row(field.row, value); - subgrids[3 * subgrid.row + 1].clear_row(field.row, value); - subgrids[3 * subgrid.row + 2].clear_row(field.row, value); - - subgrids[subgrid.col + 0].clear_col(field.col, value); - subgrids[subgrid.col + 3].clear_col(field.col, value); - subgrids[subgrid.col + 6].clear_col(field.col, value); - - rows[ab.row].remove(ab.col); - cols[ab.col].remove(ab.row); - - rows[ab.row].clear(value); - cols[ab.col].clear(value); + std::cout << "setting " << (int)value << ": " << ab << std::endl; - for (uint8_t i = 0; i < 9; i++) { - rows[i].remove(ab.col, value); - cols[i].remove(ab.row, value); + _zero(ab, value); - uint8_t trow = subgrid.row * 3 + i / 3; - uint8_t tcol = subgrid.col * 3 + i % 3; + for (uint8_t i = 0; i < 3; i++) { + // clear current block + _clear_row(subgrid, i, value); - rows[trow].remove(tcol, value); - cols[tcol].remove(trow, value); + // clear intersecting row and col + _clear_row(3 * subgrid.row + i, field.row, value); + _clear_col(subgrid.col + 3 * i, field.col, value); } - std::cout << "setting " << (int)value << ": " << ab << std::endl; - - subgrids[::field(subgrid)].set(field, value); + subgrids[subgrid].set(field, value); } bool solve() { @@ -370,9 +322,11 @@ class Grid { for (uint8_t subgrid = 0; subgrid < 9; subgrid++) { const auto lones = subgrids[subgrid].get_lone(); for (const auto [field, val] : lones) { - set(subgrid, field, val); - std::cout << "lone: " << subgrid << " " << (int)field << " " << int(val) << std::endl; + std::cout << "lone: " << (int)subgrid << " " << (int)field << " " << int(val) + << std::endl; + + set(subgrid, field, val); changes++; } } @@ -383,7 +337,6 @@ class Grid { const uint8_t subgrid = (row / 3) * 3 + col / 3; const uint8_t field = (row % 3) * 3 + col % 3; - std::cout << (int)row << " " << (int)col << std::endl; std::cout << "lone row: " << (int)subgrid << " " << (int)field << " " << int(val) << std::endl; @@ -409,21 +362,17 @@ class Grid { for (uint8_t i = 0; i < 9; i++) { const auto naked = subgrids[i].check_naked(); for (const auto [field, mask] : naked) { - subgrids[i].mask(field, mask); const auto rc = row_col_t(i).absolute(field); uint16_t tmask = mask; while (tmask) { uint16_t idx = std::countr_zero(tmask); - - subgrids[i].ref_remove(field, idx); - rows[rc.row].remove(rc.col); - cols[rc.col].remove(rc.row); - + _clear(i, field, idx); tmask ^= 1ull << idx; } - std::cout << "naked: " << i << " " << (int)field << " " << int(mask) << std::endl; + std::cout << "naked: " << (int)i << " " << (int)field << " " << std::bitset<9>(mask) + << std::endl; changes++; } } @@ -434,8 +383,8 @@ class Grid { for (const auto [col, val] : rays[0]) { static uint8_t mapping[9][2] = {{3, 6}, {4, 7}, {5, 8}, {0, 6}, {1, 7}, {2, 8}, {0, 3}, {1, 4}, {2, 5}}; - subgrids[mapping[i][0]].clear_col(col, val); - subgrids[mapping[i][1]].clear_col(col, val); + _clear_col(mapping[i][0], col, val); + _clear_col(mapping[i][1], col, val); std::cout << "col: " << (int)i << " " << (int)col << " " << (int)val << std::endl; changes++; @@ -444,8 +393,8 @@ class Grid { for (const auto [row, val] : rays[1]) { static uint8_t mapping[9][2] = {{1, 2}, {0, 2}, {0, 1}, {4, 5}, {3, 5}, {3, 4}, {7, 8}, {6, 8}, {6, 7}}; - subgrids[mapping[i][0]].clear_row(row, val); - subgrids[mapping[i][1]].clear_row(row, val); + _clear_row(mapping[i][0], row, val); + _clear_row(mapping[i][1], row, val); std::cout << "row: " << (int)i << " " << (int)row << " " << (int)val << std::endl; changes++; @@ -458,6 +407,7 @@ class Grid { for (uint8_t i = 0; i < 9; i++) { if (!subgrids[i].is_finished()) return false; } + return true; } @@ -468,7 +418,7 @@ class Grid { for (uint8_t j = 0; j < 9; j++) { const row_col_t subgrid = {uint8_t(i / 3), uint8_t(j / 3)}; const row_col_t field = {uint8_t(i % 3), uint8_t(j % 3)}; - std::bitset<9> value = subgrids[::field(subgrid)].get(field); + std::bitset<9> value = subgrids[subgrid].get(field); std::cout << value << " "; if (j % 3 == 2) std::cout << " "; } @@ -481,7 +431,7 @@ class Grid { for (uint8_t j = 0; j < 9; j++) { const row_col_t subgrid = {uint8_t(i / 3), uint8_t(j / 3)}; const row_col_t field = {uint8_t(i % 3), uint8_t(j % 3)}; - std::bitset<9> value = subgrids[::field(subgrid)].get_ref(::field(field)); + std::bitset<9> value = subgrids[subgrid].get_ref(field); std::cout << value << " "; if (j % 3 == 2) std::cout << " "; } @@ -512,7 +462,7 @@ class Grid { for (uint8_t j = 0; j < 9; j++) { const row_col_t subgrid = {uint8_t(i / 3), uint8_t(j / 3)}; const row_col_t field = {uint8_t(i % 3), uint8_t(j % 3)}; - std::cout << (int)subgrids[::field(subgrid)].value(field) << " "; + std::cout << (int)subgrids[subgrid].value(field) << " "; if (j % 3 == 2) std::cout << " "; } std::cout << std::endl; @@ -521,6 +471,38 @@ class Grid { } private: + void _clear(row_col_t ab, uint8_t value) { + rows[ab.row].clear(ab.col, value); + cols[ab.col].clear(ab.row, value); + } + + void _clear(row_col_t ab) { + rows[ab.row].clear(ab.col); + cols[ab.col].clear(ab.row); + } + + void _zero(row_col_t ab, uint8_t value) { + rows[ab.row].zero(value); + cols[ab.col].zero(value); + } + + void _clear(row_col_t sg, row_col_t field, uint8_t value) { + _clear(sg.absolute(field), value); + subgrids[sg].clear(field, value); + } + + void _clear_row(row_col_t sg, uint8_t row, uint8_t value) { + for (uint8_t i = 0; i < 3; i++) { + _clear(sg, {row, i}, value); + } + } + + void _clear_col(row_col_t sg, uint8_t col, uint8_t value) { + for (uint8_t i = 0; i < 3; i++) { + _clear(sg, {i, col}, value); + } + } + Subgrid subgrids[9]; Ref rows[9]; Ref cols[9];