diff --git a/dlx/include/dlx.hpp b/dlx/include/dlx.hpp index 6f29c88..6242c17 100644 --- a/dlx/include/dlx.hpp +++ b/dlx/include/dlx.hpp @@ -72,4 +72,4 @@ auto ForallCover(Dlx& dlx, auto cb) { } // namespace -#endif \ No newline at end of file +#endif diff --git a/dlx/src/dlx.cpp b/dlx/src/dlx.cpp index bf7a2d0..d28c021 100644 --- a/dlx/src/dlx.cpp +++ b/dlx/src/dlx.cpp @@ -6,14 +6,16 @@ namespace dlx { + template struct CellView; +template 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; @@ -28,44 +30,34 @@ struct Cell { auto LR_insert(Cell* k) -> void; auto UD_insert(Cell* k) -> void; - auto CoverCol() -> void; + auto CoverCol() -> void; auto UncoverCol() -> void; auto rightwards() -> CellView<&Cell::R>; - auto leftwards() -> CellView<&Cell::L>; - auto upwards() -> CellView<&Cell::U>; - auto downwards() -> CellView<&Cell::D>; + auto leftwards() -> CellView<&Cell::L>; + 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 +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 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 { return CellIterator{cell->*direction}; } + auto end() const -> CellIterator { return CellIterator{cell}; }; }; -template -auto CellView::begin() const -> CellView { return {cell->*direction}; } - -template -auto CellView::end() const -> CellView { return {cell}; } - -template -auto CellView::operator*() -> Cell* { return cell; } - -template -auto CellView::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(); @@ -268,4 +260,4 @@ auto Dlx::Solve( recurse(recurse); } -} // namespace \ No newline at end of file +} // namespace