aocpp/dlx/include/dlx.hpp

75 lines
1.9 KiB
C++
Raw Normal View History

2022-11-19 14:59:21 -08:00
#ifndef DLX_DLX_HPP_
#define DLX_DLX_HPP_
#include <cstddef>
#include <functional>
#include <vector>
2022-11-20 13:52:18 -08:00
#include <utility>
2022-11-19 14:59:21 -08:00
namespace dlx {
2022-11-20 11:15:15 -08:00
struct Cell;
2022-11-19 14:59:21 -08:00
2022-11-20 11:15:15 -08:00
class Dlx final {
2022-11-19 14:59:21 -08:00
std::vector<Cell*> ctab_;
std::vector<Cell*> rtab_;
Cell* root_;
auto AddCol() -> void;
auto AddRow() -> void;
auto AllocCol(std::size_t n) -> void;
auto AllocRow(std::size_t n) -> void;
public:
Dlx();
~Dlx();
2022-11-20 10:09:23 -08:00
Dlx(Dlx const&) = delete;
auto operator=(Dlx const&) -> Dlx& = delete;
Dlx(Dlx &&);
auto operator=(Dlx &&) -> Dlx&;
2022-11-19 14:59:21 -08:00
// Returns number of rows.
auto Rows() const -> std::size_t;
// Returns number of columns.
auto Cols() const -> std::size_t;
// Places a 1 in the given row and column.
// Increases the number of rows and columns if necessary.
auto Set(std::size_t row, std::size_t col) -> void;
2022-11-20 13:52:18 -08:00
// Marks a column as optional: a solution need not cover the given column,
// but it still must respect the constraints it entails.
2022-11-19 14:59:21 -08:00
auto MarkOptional(std::size_t col) -> void;
2022-11-20 10:09:23 -08:00
// Removes a row from consideration.
2022-11-19 14:59:21 -08:00
// Should only be called after all dlx_set() calls.
2022-11-20 10:09:23 -08:00
auto RemoveRow(std::size_t row) -> void;
2022-11-19 14:59:21 -08:00
2022-11-20 10:09:23 -08:00
// Picks a row to be part of the solution.
// Should only be called after all Set() calls and RemoveRows() calls.
2022-11-19 14:59:21 -08:00
// TODO: Check the row can be legally chosen.
2022-11-20 10:09:23 -08:00
auto PickRow(std::size_t row) -> void;
2022-11-19 14:59:21 -08:00
auto Solve(
2022-11-20 13:52:18 -08:00
std::function<bool(std::size_t, std::size_t, std::size_t)> try_cb,
std::function<bool()> undo_cb,
std::function<bool()> found_cb,
std::function<bool(std::size_t)> stuck_cb) -> void;
2022-11-19 14:59:21 -08:00
};
auto ForallCover(Dlx& dlx, auto cb) {
std::vector<std::size_t> sol;
dlx.Solve(
2022-11-20 13:52:18 -08:00
[&](std::size_t c, std::size_t s, std::size_t r) { sol.push_back(r); return false; },
[&](){ sol.pop_back(); return false; },
[&](){ return cb(std::as_const(sol)); },
[](std::size_t){ return false; }
2022-11-19 14:59:21 -08:00
);
}
} // namespace
#endif