dlx iterators
This commit is contained in:
parent
43cf5942bc
commit
b053686349
|
@ -72,4 +72,4 @@ auto ForallCover(Dlx& dlx, auto cb) {
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,14 +6,16 @@
|
||||||
|
|
||||||
namespace dlx {
|
namespace dlx {
|
||||||
|
|
||||||
|
|
||||||
template <Cell* Cell::* direction> struct CellView;
|
template <Cell* Cell::* direction> struct CellView;
|
||||||
|
template <Cell* Cell::* direction> struct CellIterator;
|
||||||
|
|
||||||
struct Cell {
|
struct Cell {
|
||||||
Cell *U, *D, *L, *R;
|
Cell *U, *D, *L, *R;
|
||||||
std::size_t n;
|
std::size_t n;
|
||||||
union {
|
union {
|
||||||
Cell* c;
|
Cell* c; // pointer to column cell belongs to
|
||||||
std::size_t s;
|
std::size_t s; // number of elements in column
|
||||||
};
|
};
|
||||||
|
|
||||||
auto LR_self() -> void;
|
auto LR_self() -> void;
|
||||||
|
@ -28,44 +30,34 @@ struct Cell {
|
||||||
auto LR_insert(Cell* k) -> void;
|
auto LR_insert(Cell* k) -> void;
|
||||||
auto UD_insert(Cell* k) -> void;
|
auto UD_insert(Cell* k) -> void;
|
||||||
|
|
||||||
auto CoverCol() -> void;
|
auto CoverCol() -> void;
|
||||||
auto UncoverCol() -> void;
|
auto UncoverCol() -> void;
|
||||||
|
|
||||||
auto rightwards() -> CellView<&Cell::R>;
|
auto rightwards() -> CellView<&Cell::R>;
|
||||||
auto leftwards() -> CellView<&Cell::L>;
|
auto leftwards() -> CellView<&Cell::L>;
|
||||||
auto upwards() -> CellView<&Cell::U>;
|
auto upwards() -> CellView<&Cell::U>;
|
||||||
auto downwards() -> CellView<&Cell::D>;
|
auto downwards() -> CellView<&Cell::D>;
|
||||||
|
|
||||||
|
static auto ColNew() -> Cell*;
|
||||||
auto ColAdd(std::size_t row_id) -> 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>
|
template <Cell* Cell::* direction>
|
||||||
struct CellView {
|
struct CellView {
|
||||||
Cell* cell;
|
Cell* cell;
|
||||||
|
auto begin() const -> CellIterator<direction> { return CellIterator<direction>{cell->*direction}; }
|
||||||
auto operator==(CellView const&) const -> bool = default;
|
auto end() const -> CellIterator<direction> { return CellIterator<direction>{cell}; };
|
||||||
auto begin() const -> CellView;
|
|
||||||
auto end() const -> CellView;
|
|
||||||
auto operator*() -> Cell*;
|
|
||||||
auto operator++() -> CellView&;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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::LR_self() -> void { L = R = this; }
|
||||||
auto Cell::UD_self() -> void { U = D = this; }
|
auto Cell::UD_self() -> void { U = D = this; }
|
||||||
auto Cell::LR_delete() -> void { L->R = R; R->L = L; }
|
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 {
|
auto Cell::CoverCol() -> void {
|
||||||
LR_delete();
|
LR_delete();
|
||||||
for (auto const i : downwards()) {
|
for (auto & i : downwards()) {
|
||||||
for (auto const j : i->rightwards()) {
|
for (auto & j : i.rightwards()) {
|
||||||
j->UD_delete();
|
j.UD_delete();
|
||||||
j->c->s--;
|
j.c->s--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto Cell::UncoverCol() -> void {
|
auto Cell::UncoverCol() -> void {
|
||||||
for (auto const i : upwards()) {
|
for (auto & i : upwards()) {
|
||||||
for (auto const j : i->leftwards()) {
|
for (auto & j : i.leftwards()) {
|
||||||
j->c->s++;
|
j.c->s++;
|
||||||
j->UD_restore();
|
j.UD_restore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LR_restore();
|
LR_restore();
|
||||||
|
@ -198,8 +190,8 @@ auto Dlx::Set(std::size_t row, std::size_t col) -> void {
|
||||||
// Ignore duplicates.
|
// Ignore duplicates.
|
||||||
if (r->c->n == col) return;
|
if (r->c->n == col) return;
|
||||||
|
|
||||||
for (auto const cursor : r->rightwards()) {
|
for (auto const& cursor : r->rightwards()) {
|
||||||
if (cursor->c->n == col) return;
|
if (cursor.c->n == col) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise insert at end of LR list.
|
// 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 {
|
auto Dlx::PickRow(std::size_t i) -> void {
|
||||||
if (auto r = rtab_.at(i)) {
|
if (auto r = rtab_.at(i)) {
|
||||||
r->c->CoverCol();
|
r->c->CoverCol();
|
||||||
for (auto const j : r->rightwards()) {
|
for (auto & j : r->rightwards()) {
|
||||||
j->c->CoverCol();
|
j.c->CoverCol();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,9 +211,9 @@ auto Dlx::RemoveRow(std::size_t i) -> void {
|
||||||
if (auto & r = rtab_.at(i)) {
|
if (auto & r = rtab_.at(i)) {
|
||||||
r->UD_delete();
|
r->UD_delete();
|
||||||
r->c->s--;
|
r->c->s--;
|
||||||
for (auto const j : r->rightwards()) {
|
for (auto & j : r->rightwards()) {
|
||||||
j->UD_delete();
|
j.UD_delete();
|
||||||
j->c->s--;
|
j.c->s--;
|
||||||
}
|
}
|
||||||
r = nullptr;
|
r = nullptr;
|
||||||
}
|
}
|
||||||
|
@ -240,9 +232,9 @@ auto Dlx::Solve(
|
||||||
}
|
}
|
||||||
|
|
||||||
auto s = c->s;
|
auto s = c->s;
|
||||||
for (auto const i : root_->rightwards()) {
|
for (auto & i : root_->rightwards()) {
|
||||||
if (i->s < s) {
|
if (i.s < s) {
|
||||||
s = (c = i)->s;
|
s = (c = &i)->s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,15 +243,15 @@ auto Dlx::Solve(
|
||||||
}
|
}
|
||||||
|
|
||||||
c->CoverCol();
|
c->CoverCol();
|
||||||
for (auto const r : c->downwards()) {
|
for (auto & r : c->downwards()) {
|
||||||
if (try_cb(c->n, s, r->n)) [[unlikely]] return true;
|
if (try_cb(c->n, s, r.n)) [[unlikely]] return true;
|
||||||
for (auto const j : r->rightwards()) {
|
for (auto & j : r.rightwards()) {
|
||||||
j->c->CoverCol();
|
j.c->CoverCol();
|
||||||
}
|
}
|
||||||
if (self(self)) [[unlikely]] return true;
|
if (self(self)) [[unlikely]] return true;
|
||||||
if (undo_cb()) [[unlikely]] return true;
|
if (undo_cb()) [[unlikely]] return true;
|
||||||
for (auto const j : r->leftwards()) {
|
for (auto & j : r.leftwards()) {
|
||||||
j->c->UncoverCol();
|
j.c->UncoverCol();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
c->UncoverCol();
|
c->UncoverCol();
|
||||||
|
@ -268,4 +260,4 @@ auto Dlx::Solve(
|
||||||
recurse(recurse);
|
recurse(recurse);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
Loading…
Reference in New Issue
Block a user