dlx iterators

This commit is contained in:
Eric Mertens 2022-11-21 14:14:20 -08:00
parent 43cf5942bc
commit b053686349
2 changed files with 46 additions and 54 deletions

View File

@ -6,14 +6,16 @@
namespace dlx {
template <Cell* Cell::* direction> struct CellView;
template <Cell* Cell::* direction> struct CellIterator;
struct Cell {
Cell *U, *D, *L, *R;
std::size_t n;
union {
Cell* c;
std::size_t s;
Cell* c; // pointer to column cell belongs to
std::size_t s; // number of elements in column
};
auto LR_self() -> void;
@ -36,36 +38,26 @@ struct Cell {
auto upwards() -> CellView<&Cell::U>;
auto downwards() -> CellView<&Cell::D>;
static auto ColNew() -> Cell*;
auto ColAdd(std::size_t row_id) -> Cell*;
static Cell* ColNew();
};
template <Cell* Cell::* direction>
struct CellIterator {
Cell* cell;
auto operator==(CellIterator const&) const -> bool = default;
auto operator* () const -> Cell& { return *cell; }
auto operator->() const -> Cell* { return cell; }
auto operator++() -> CellIterator& { cell = cell->*direction; return *this; }
};
template <Cell* Cell::* direction>
struct CellView {
Cell* cell;
auto operator==(CellView const&) const -> bool = default;
auto begin() const -> CellView;
auto end() const -> CellView;
auto operator*() -> Cell*;
auto operator++() -> CellView&;
auto begin() const -> CellIterator<direction> { return CellIterator<direction>{cell->*direction}; }
auto end() const -> CellIterator<direction> { return CellIterator<direction>{cell}; };
};
template <Cell* Cell::* direction>
auto CellView<direction>::begin() const -> CellView { return {cell->*direction}; }
template <Cell* Cell::* direction>
auto CellView<direction>::end() const -> CellView { return {cell}; }
template <Cell* Cell::* direction>
auto CellView<direction>::operator*() -> Cell* { return cell; }
template <Cell* Cell::* direction>
auto CellView<direction>::operator++() -> CellView& {
cell = cell->*direction;
return *this;
}
auto Cell::LR_self() -> void { L = R = this; }
auto Cell::UD_self() -> void { U = D = this; }
auto Cell::LR_delete() -> void { L->R = R; R->L = L; }
@ -95,19 +87,19 @@ auto Cell::ColAdd(std::size_t row_id) -> Cell*
auto Cell::CoverCol() -> void {
LR_delete();
for (auto const i : downwards()) {
for (auto const j : i->rightwards()) {
j->UD_delete();
j->c->s--;
for (auto & i : downwards()) {
for (auto & j : i.rightwards()) {
j.UD_delete();
j.c->s--;
}
}
}
auto Cell::UncoverCol() -> void {
for (auto const i : upwards()) {
for (auto const j : i->leftwards()) {
j->c->s++;
j->UD_restore();
for (auto & i : upwards()) {
for (auto & j : i.leftwards()) {
j.c->s++;
j.UD_restore();
}
}
LR_restore();
@ -198,8 +190,8 @@ auto Dlx::Set(std::size_t row, std::size_t col) -> void {
// Ignore duplicates.
if (r->c->n == col) return;
for (auto const cursor : r->rightwards()) {
if (cursor->c->n == col) return;
for (auto const& cursor : r->rightwards()) {
if (cursor.c->n == col) return;
}
// Otherwise insert at end of LR list.
@ -209,8 +201,8 @@ auto Dlx::Set(std::size_t row, std::size_t col) -> void {
auto Dlx::PickRow(std::size_t i) -> void {
if (auto r = rtab_.at(i)) {
r->c->CoverCol();
for (auto const j : r->rightwards()) {
j->c->CoverCol();
for (auto & j : r->rightwards()) {
j.c->CoverCol();
}
}
}
@ -219,9 +211,9 @@ auto Dlx::RemoveRow(std::size_t i) -> void {
if (auto & r = rtab_.at(i)) {
r->UD_delete();
r->c->s--;
for (auto const j : r->rightwards()) {
j->UD_delete();
j->c->s--;
for (auto & j : r->rightwards()) {
j.UD_delete();
j.c->s--;
}
r = nullptr;
}
@ -240,9 +232,9 @@ auto Dlx::Solve(
}
auto s = c->s;
for (auto const i : root_->rightwards()) {
if (i->s < s) {
s = (c = i)->s;
for (auto & i : root_->rightwards()) {
if (i.s < s) {
s = (c = &i)->s;
}
}
@ -251,15 +243,15 @@ auto Dlx::Solve(
}
c->CoverCol();
for (auto const r : c->downwards()) {
if (try_cb(c->n, s, r->n)) [[unlikely]] return true;
for (auto const j : r->rightwards()) {
j->c->CoverCol();
for (auto & r : c->downwards()) {
if (try_cb(c->n, s, r.n)) [[unlikely]] return true;
for (auto & j : r.rightwards()) {
j.c->CoverCol();
}
if (self(self)) [[unlikely]] return true;
if (undo_cb()) [[unlikely]] return true;
for (auto const j : r->leftwards()) {
j->c->UncoverCol();
for (auto & j : r.leftwards()) {
j.c->UncoverCol();
}
}
c->UncoverCol();