diff --git a/backtracking/magic_sequence.cpp b/backtracking/magic_sequence.cpp new file mode 100644 index 000000000..5fef52386 --- /dev/null +++ b/backtracking/magic_sequence.cpp @@ -0,0 +1,74 @@ +/* + * @brief [Magic sequence](https://www.csplib.org/Problems/prob019/) + * + * @details + * + * @author [Jxtopher](https://github.com/jxtopher) + */ + +#include +#include +#include +#include +#include +#include + +namespace backtracking { +namespace magic_sequence { + using sequence_t = std::vector; + + void print(const sequence_t& s) { + for(auto item : s) std::cout << item << " "; + std::cout << std::endl; + } + + // Check if it's a magic sequence + bool is_magic(const sequence_t& s) { + for(unsigned int i = 0; i < s.size(); i++) + if(std::count(s.cbegin(), s.cend(), i) != s[i]) return false; + return true; + } + + // Filtering of sub-solutions + // true if the sub-solution is valid otherwise false + bool filtering(const sequence_t& s, unsigned int depth) { + return std::accumulate(s.cbegin(), s.cbegin() + depth, static_cast(0)) <= + s.size(); + } + + void solve(sequence_t& s, std::list& ret, unsigned int depth = 0) { + if(depth == s.size()) { + if(is_magic(s)) ret.push_back(s); + } else { + for(unsigned int i = 0; i < s.size(); i++) { + s[depth] = i; + if(filtering(s, depth + 1)) solve(s, ret, depth + 1); + } + } + } + +} // namespace magic_sequence + +} // namespace backtracking + +using namespace backtracking::magic_sequence; + +static void test() { + sequence_t s_magic = {6, 2, 1, 0, 0, 0, 1, 0, 0, 0}; + assert(is_magic(s_magic)); + + sequence_t s_not_magic = {5, 2, 1, 0, 0, 0, 1, 0, 0, 0}; + assert(!is_magic(s_not_magic)); +} + +int main() { + test(); + + for(unsigned int i = 2; i < 12; i++) { + std::cout << "Solution for n = " << i << std::endl; + std::list r1; + sequence_t s1(i, i); + solve(s1, r1); + for(auto item : r1) print(item); + } +}