mirror of
https://github.com/TheAlgorithms/C-Plus-Plus.git
synced 2026-04-01 17:52:40 +08:00
feat: solving magic sequence problem with backtracking (#1533)
* Create magic_sequence.cpp * update code formatter * updating DIRECTORY.md * Update magic_sequence.cpp * Delete settings.json * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update magic_sequence.cpp * Revert "Delete settings.json" This reverts commit64b08dee6d. * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * clang-format and clang-tidy fixes for2263f033* Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update magic_sequence.cpp * Update magic_sequence.cpp * Update magic_sequence.cpp * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update magic_sequence.cpp * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * clang-format and clang-tidy fixes forf889fb4f* Update backtracking/magic_sequence.cpp Co-authored-by: David Leal <halfpacho@gmail.com> * Update magic_sequence.cpp * fix: Apply suggestions from code review Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Co-authored-by: David Leal <halfpacho@gmail.com>
This commit is contained in:
135
backtracking/magic_sequence.cpp
Normal file
135
backtracking/magic_sequence.cpp
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* @brief [Magic sequence](https://www.csplib.org/Problems/prob019/)
|
||||
* implementation
|
||||
*
|
||||
* @details Solve the magic sequence problem with backtracking
|
||||
*
|
||||
* "A magic sequence of length $n$ is a sequence of integers $x_0
|
||||
* \ldots x_{n-1}$ between $0$ and $n-1$, such that for all $i$
|
||||
* in $0$ to $n-1$, the number $i$ occurs exactly $x_i$ times in
|
||||
* the sequence. For instance, $6,2,1,0,0,0,1,0,0,0$ is a magic
|
||||
* sequence since $0$ occurs $6$ times in it, $1$ occurs twice, etc."
|
||||
* Quote taken from the [CSPLib](https://www.csplib.org/Problems/prob019/)
|
||||
* website
|
||||
*
|
||||
* @author [Jxtopher](https://github.com/Jxtopher)
|
||||
*/
|
||||
|
||||
#include <algorithm> /// for std::count
|
||||
#include <cassert> /// for assert
|
||||
#include <iostream> /// for IO operations
|
||||
#include <list> /// for std::list
|
||||
#include <numeric> /// for std::accumulate
|
||||
#include <vector> /// for std::vector
|
||||
|
||||
/**
|
||||
* @namespace backtracking
|
||||
* @brief Backtracking algorithms
|
||||
*/
|
||||
namespace backtracking {
|
||||
/**
|
||||
* @namespace magic_sequence
|
||||
* @brief Functions for the [Magic
|
||||
* sequence](https://www.csplib.org/Problems/prob019/) implementation
|
||||
*/
|
||||
namespace magic_sequence {
|
||||
using sequence_t =
|
||||
std::vector<unsigned int>; ///< Definition of the sequence type
|
||||
/**
|
||||
* @brief Print the magic sequence
|
||||
* @param s working memory for the sequence
|
||||
*/
|
||||
void print(const sequence_t& s) {
|
||||
for (const auto& item : s) std::cout << item << " ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if the sequence is magic
|
||||
* @param s working memory for the sequence
|
||||
* @returns true if it's a magic sequence
|
||||
* @returns false if it's NOT 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sub-solutions filtering
|
||||
* @param s working memory for the sequence
|
||||
* @param depth current depth in tree
|
||||
* @returns true if the sub-solution is valid
|
||||
* @returns false if the sub-solution is NOT valid
|
||||
*/
|
||||
bool filtering(const sequence_t& s, unsigned int depth) {
|
||||
return std::accumulate(s.cbegin(), s.cbegin() + depth,
|
||||
static_cast<unsigned int>(0)) <= s.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Solve the Magic Sequence problem
|
||||
* @param s working memory for the sequence
|
||||
* @param ret list of the valid magic sequences
|
||||
* @param depth current depth in the tree
|
||||
*/
|
||||
void solve(sequence_t* s, std::list<sequence_t>* 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
|
||||
|
||||
/**
|
||||
* @brief Self-test implementations
|
||||
* @returns void
|
||||
*/
|
||||
static void test() {
|
||||
// test a valid magic sequence
|
||||
backtracking::magic_sequence::sequence_t s_magic = {6, 2, 1, 0, 0,
|
||||
0, 1, 0, 0, 0};
|
||||
assert(backtracking::magic_sequence::is_magic(s_magic));
|
||||
|
||||
// test a non-valid magic sequence
|
||||
backtracking::magic_sequence::sequence_t s_not_magic = {5, 2, 1, 0, 0,
|
||||
0, 1, 0, 0, 0};
|
||||
assert(!backtracking::magic_sequence::is_magic(s_not_magic));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Main function
|
||||
* @returns 0 on exit
|
||||
*/
|
||||
int main() {
|
||||
test(); // run self-test implementations
|
||||
|
||||
// solve magic sequences of size 2 to 11 and print the solutions
|
||||
for (unsigned int i = 2; i < 12; i++) {
|
||||
std::cout << "Solution for n = " << i << std::endl;
|
||||
// valid magic sequence list
|
||||
std::list<backtracking::magic_sequence::sequence_t> list_of_solutions;
|
||||
// initialization of a sequence
|
||||
backtracking::magic_sequence::sequence_t s1(i, i);
|
||||
// launch of solving the problem
|
||||
backtracking::magic_sequence::solve(&s1, &list_of_solutions);
|
||||
// print solutions
|
||||
for (const auto& item : list_of_solutions) {
|
||||
backtracking::magic_sequence::print(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user