This is my version of the possible permutations of a string challenge. Please give me feedback or criticism. There are two vectors here: positions
and pointed_to
. positions[i]
holds the index of the i'th character in the permutation. pointed_to[i]
is true if the index of the i'th character in the original string is present somewhere inside the positions
vector. I like to think of the positions
vector as "character pointers". There are as many "character pointers" as there are characters in the original string. Each "character pointer" points to a character in the original string. The position[0]
"points to" the first character in the permutation, the position[1]
"points to" the second character in the permutation, and so on.
Inside the function, there is a loop which picks a char in the original string for each "character pointer" to "point to". Each char in the string can be pointed to by no more than one "character pointer". So we are looping until we find an open position for that "character pointer", a char to which no other pointers point to, pointed_to = false
.
The position array is pass by reference, or it could be a global variable, because we don't care about storing the previous states of it's data in the recursion stack. Each newly created stack frame finds a position for the 0'th "pointer". This corresponds to position[0]
. As the recursive stack grows, it fills in position[1]
, then position[2]
, [3]
, ... and so on. When stack frames get popped off the stack, we no longer care about the "residue" left in position[ the higher insides ]
. This is similar in principle to how stack frames in the real recursive stack are not deleted, but simply considered as garbage values. All values position[a]
where a > current_position
are also considered to be garbage values. When the stack grows to be the size of the string, all the positions will have been filled up anyway, and so we can just print the permutation by following the pointers.
The pointed_by
array is stored on the stack, however, and it is passed by value. In positions, only a single element was considered to be data associated with the current stack frame, so we could place it outside the stack. However, the whole pointed_by
array is considered to be data associated with the current stack frame. That way when the stack frames are being popped off, we preserve the whole old state of the pointed_to
array as it was originally.
I know that this explanation sounds kind of confusing, so sorry about that. Well, this algorithm actually works, and only O(n) memory is taken up.
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
template <typename TYPE>
void print_vector(vector<TYPE> vect)
{
for (auto x : vect) {
cerr << x << ' ';
}
}
void print_permutations(const string& input,
vector<int>& positions, vector<bool> pointed_to,
size_t current_position, size_t string_length)
{
if (current_position == string_length) {
for (size_t i = 0; i < string_length; ++i) {
cout << input.at( positions.at(i) );
}
cout << endl;
return;
}
for (size_t i = 0; i < string_length; ++i) {
// not empty
if (pointed_to.at(i)) {
continue;
// empty
} else {
positions.at(current_position) = i;
pointed_to.at(i) = true;
print_permutations(input, positions, pointed_to, current_position + 1, string_length);
pointed_to.at(i) = false;
}
}
return;
}
int main()
{
string input;
cout << " > ";
cin >> input;
cout << endl;
size_t string_length = input.length();
vector<int> positions(string_length);
vector<bool> pointed_to(string_length, false);
print_permutations(input, positions, pointed_to, 0, string_length);
return EXIT_SUCCESS;
}