Generate the lexicographically first permutation(recursive backtracking) - c++

The input is a number n, a number m, and an array of size 3*n, whose elements are either 0s or numbers from 1 to n, where 1<=n,m<=30. I need to make an algorithm to generate the lexicographically first permutation of the set{1,...,n}, where every element appears exactly 3 times, where two equal numbers have a minimum ofm different numbers between them. Only the 0s are to be replaced, while any number that isn't 0 has to stay the same.
For example, for n=5, m=1 and the array 1 0 0 0 0 0 3 0 0 0 0 0 0 4 5 the output should be 1 2 1 2 1 2 3 4 3 5 3 4 5 4 5.
I came up with this code. It doesn't output the lexicographically first permutation. It outputs
1 2 3 4 5 1 3 2 3 4 5 1 2 4 5
#include <array>
#include <iostream>
using namespace std;
int counters[100]={3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3};
bool verify_permutation(int V[], int n, int m){
array<int,100> POZ;
POZ.fill(m);;
for(int i = 1;i<=3*n;i++){
if(V[i]==0)
return false;
for(int j = 1;j<=3*n;j++){
if(POZ[V[j]]<m)
return false;
POZ[V[j]]=0;
for(int k = 1;k<=n;k++){
POZ[k]++;
}
}
}
return true;
}
int j = 1;
void backtracking(int V[], int x, int m, int n){
if(verify_permutation(V,n,m)){
for(int i = 1;i<=3*n;i++)
cout<<V[i]<<' ';
return;
}
for(int i=1;i<=3*n;i++){
if(counters[j]==0)
continue;
if(V[i]!=0){
counters[V[i]]--;
continue;
}
j++;
if(j>n)
j=1;
if(V[i]==0){
counters[j]--;
V[i]=j;
backtracking(V,j,m,n);
counters[j]++;
}
}
return;
}
int main(){
int V[31];
int n,m;
cin>>n>>m;
if(m>=n){
cout<<-1;
return 0;
}
for(int i = 1; i <= 3*n; i++){
cin >> V[i];
}
backtracking(V, 1, m, n);
}
What is wrong with the code?

Related

Permutations of an int array, using recursion

Exercise is as follows:
Generate every possible sequence whose elements are from the set {0,
1, 2} where 0 occurs m times, 1 occurs p times, and 2 occurs q times. The input file
contains three natural numbers separated by spaces, with a maximum value of 100. The solution must be written to the output file line by line
in lexicographic order. Each line should contain the elements of the series
separated by spaces.
If input is:
1 0 2
Output should be:
0 2 2
2 0 2
2 2 0
It's also stated, that I have to use recursion, and the input and output should be to .txt files.
So, I found a popular recursion for permutations which occurred on multiple sites (like this), but for some weird reason, it's not working properly for me..
The way I tried doing this exercise (there might be a smarter way) is by generating a vector from the input, and the using the permutation function with it. But my output is like this:
0 2 2
0 2 2
2 0 2
2 2 0
2 2 0
2 0 2
As you can see, every result appears twice, which is obviously not good..
Code is here below:
#include <iostream>
#include <vector>
#include <fstream>
using namespace std;
void input(int& m, int& p, int& q)
{
ifstream fin("input.txt");
fin >> m >> p >> q;
fin.close();
}
void fillVec(vector <int>& elements, int m, int p, int q)
{
fill_n(elements.begin() + m, p, 1); // filling the vectors with correct amount of numbers. The 0's all already there, so I only put the 1's, and the 2's in.
fill_n(elements.begin() + m + p, q, 2);
}
void print(const vector<int>& nums, ofstream& fout)
{
for (int a : nums) { fout << a << ' '; }
fout << endl;
}
void permute(vector<int>& nums, int n, ofstream& fout)
{
if (n == nums.size())
{
print(nums, fout);
}
else
{
for (int i = n; i < nums.size(); i++)
{
swap(nums[n], nums[i]);
permute(nums, n + 1, fout);
swap(nums[n], nums[i]);
}
}
}
int main()
{
int m, p, q;
input(m, p, q);
vector <int> elements(m + p + q);
fillVec(elements, m, p, q);
ofstream fout("output.txt");
permute(elements, 0, fout);
fout.close();
return 0;
}
I tried debugging, also looked at it multiple times to check that I copied the algorithm correctly, but can't find out what's the problem. It might be something pretty simple, I'm not sure..
Here's what I came up with. Each recursive step will attempt to append "0", "1", or "2" to the string being built until there's no available digits to add.
#include <iostream>
#include <string>
using namespace std;
void GeneratePermutations(int zeros, int ones, int twos, const string& leading)
{
if ((zeros <= 0) && (ones <= 0) && (twos <= 0))
{
// use "substr" to skip the leading space
if (leading.size() > 0)
{
std::cout << leading.substr(1) << endl;
}
return;
}
if (zeros > 0)
{
GeneratePermutations(zeros - 1, ones, twos, leading + " 0");
}
if (ones > 0)
{
GeneratePermutations(zeros, ones-1, twos, leading + " 1");
}
if (twos > 0)
{
GeneratePermutations(zeros, ones, twos-1, leading + " 2");
}
}
int main()
{
int zeros, ones, twos;
cin >> zeros;
cin >> ones;
cin >> twos;
GeneratePermutations(zeros, ones, twos, "");
return 0;
}
A couple of sample runs:
input : 1 0 2
output:
0 2 2
2 0 2
2 2 0
Another input: 3 1 1
output:
0 0 0 1 2
0 0 0 2 1
0 0 1 0 2
0 0 1 2 0
0 0 2 0 1
0 0 2 1 0
0 1 0 0 2
0 1 0 2 0
0 1 2 0 0
0 2 0 0 1
0 2 0 1 0
0 2 1 0 0
1 0 0 0 2
1 0 0 2 0
1 0 2 0 0
1 2 0 0 0
2 0 0 0 1
2 0 0 1 0
2 0 1 0 0
2 1 0 0 0
As you see and say yourself, you simply generate all possible permutations of the 0 2 2 array. There are 6 permutations for an array of length 3, and you correctly get them, but because there are two equal numbers, some of these permutations are equal.
However, apparently what you are required is to do generate only different permutations. Basically, this means that you need a new algorithm.
A simple solution may be to find a way to remove repeating permutations. There may be many approaches to it, starting with simply storing all the permutations and checking if you have already generated a given permutation, or storing the original array index with each number and requiring that the indices of equal number go in increasing order, etc. Or you can organize your recursion in a different way (that's what I would have done). Obviously the complexity of each approach will be different.
With std::next_permutation (which handles repetitions), a non recursive way would be:
void permute(std::vector<int>& nums, std::ostream& out)
{
assert(std::is_sorted(nums.begin(), nums.end()));
do {
print(nums, out);
} while (std::next_permutation(nums.begin(), nums.end()));
}
Demo
You can still transform above code in recursive way:
void permute(std::vector<int>& nums, std::ostream& out)
{
print(nums, out);
if (std::next_permutation(nums.begin(), nums.end())) { permute(nums, out); }
}
Demo
Your code is perfect and works as expected. The only problem is that your application is sometimes swapping the same digits, for example:
// nums = {0, 2, 2}
swap(nums[n], nums[i]); // n == 1, i == 2
// nums = {0, 2, 2}
Here you can notice that the application will swap 2 and 2, which will not make any difference.
Thus you can try something like this:
#include <iostream>
#include <vector>
#include <fstream>
// This std::vector will store all the elements that have been stored in output.txt
std::vector<std::string> output;
void input(int& m, int& p, int& q)
{
std::ifstream fin("input.txt");
fin >> m >> p >> q;
fin.close();
}
void fillVec(std::vector <int>& elements, int m, int p, int q)
{
fill_n(elements.begin() + m, p, 1); // filling the std::vectors with correct amount of numbers. The 0's all already there, so I only put the 1's, and the 2's in.
fill_n(elements.begin() + m + p, q, 2);
}
void print(const std::vector<int>& nums, std::ofstream& fout)
{
for (int a : nums) { fout << a << ' '; }
fout << std::endl;
}
void permute(std::vector<int>& nums, int n, std::ofstream& fout)
{
if (n == nums.size())
{
std::string num;
// Convert nums (int array) to num (std::string)
for (int i = 0; i < nums.size(); i++)
{
num.push_back(nums[i]);
}
// If same element found, return
for (int i = 0; i < output.size(); i++)
{
if (num == output[i]) return;
}
print(nums, fout);
// Insert element to output (std::vector)
output.push_back(num);
}
else
{
for (int i = n; i < nums.size(); i++)
{
std::swap(nums[n], nums[i]);
permute(nums, n + 1, fout);
std::swap(nums[n], nums[i]);
}
}
}
int main()
{
int m, p, q;
input(m, p, q);
std::vector <int> elements(m + p + q);
fillVec(elements, m, p, q);
std::ofstream fout("output.txt");
permute(elements, 0, fout);
fout.close();
return 0;
}
This code is the same as yours, except I've added a few checks to ensure that there are no duplicate elements. Now:
input.txt
1 0 2
output.txt (after application execution)
0 2 2
2 0 2
2 2 0
...which is desirable.
Also, consider removing the following statement:
using namespace std;
...as it's considered as bad practice.

C++ Array (disregarding a repeat number)

I am a beginner programmer and I need some assistance.
I need to write a program that reads an array of 10 numbers from a user, then scans it and figures out the most common number/s in the array itself and prints them. If there is only one number that is common in the array, only print that number. But, if there's more than one number that appears more than once, print them also in the order they appear in in the array.
For example- 1 2 3 3 4 5 6 7 8 9 - output would be 3
For- 1 2 3 4 1 2 3 4 5 6 - output would be 1 2 3 4
for- 1 1 1 1 2 2 2 3 3 4 - output would be 1 2 3
Now, the problem I've been running into, is that whenever I have a number that repeats more than twice (see third example above), the output I'm getting is the number of iterations of the loop for that number and not only that number once.
Any assistance would be welcome.
Code's attached below-
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
int array [10], index, checker, common;
main ()
{
for (index=0; index<10; index++)
{
cin >> array [index];
}
for (index=0; index<10; index++)
{
int tempcount=0;
for (checker=(index+1);checker<10;checker++)
{
if (array[index]==array[checker])
tempcount++;
}
if (tempcount>=1)
cout << array[index]<<" ";
}
return 0;
}
Use appropriate data structures for the task.
Create a std::unordered_map that maps value to number_of_occurrences, and make a single pass over the input data.
Then create another map from number_of_occurrences to value. Sort it, in descending order. Report the first value, plus any additional ones that occurred as many times as the first did.
The reason you are having problems is that anytime a number appears two times or more it will print out. A solution is that you create another variable maxCount, then find the maximum times a number appears. Then loop through the array and print out all the numbers that appears the maximum amount of times.
Hope this helps.
Jake
Rather than writing you a solution, I will try to give you some hints that you can hopefully use to correct your code. Try to keep track of the following things:
Remember the position of the first occurrence of each distinct number in the array.
Count the number of times each number appears
and combine the two to get your solution.
EDIT:
int array[] = {1, 2, 3, 4, 1, 2, 3, 4, 5, 6};
int first [11], cnt[11];
for(int i = 0; i < 11; i++){
first[i] = -1;
cnt[i] = 0;
}
int max = 0;
for(int i = 0; i < 10; i++){
cnt[array[i]]++;
if(max < array[i]) max = array[i];
}
for(int i = 0; i <= max; i++){
if(cnt[i] > 1 && first[i] == -1) {
printf(" %d", i);
first[i] = i;
}
}
You could do something like this. At any index in the array look for previous occurences of that element. If you find that that it is the first occurence of that element, you only need to look if there is an occurence of that element ahead in the array.
Lastly display the element whose frequency(here num) would be greater than 1.
for (int i = 0; i < 10; i++)
{
int presentBefore = 0;
for (int j = 0; j < i; j++) //if any previous occurence of element
{
if (array[i] == array[j]) presentBefore++;
}
if (presentBefore == 0)//if first occurence of the element
{
int num = 1;
for (int j = i + 1; j < 8; j++)// if occurences ahead in the array
{
if (array[i] == array[j]) num++;
}
if(num>1)cout<<array[i]<<" ";
}
}
Here is another solution using STL and std::set.
#include <iostream>
#include <algorithm>
#include <set>
#include <iterator>
int main()
{
int array[12] = { 1, 2, 3, 1, 2, 4, 5, 6, 3, 4, 1, 2 };
std::set<int> dupes;
for (auto it = std::begin(array), end = std::end(array); it != end; ++it)
{
if (std::count(it, end, *it) > 1 && dupes.insert(*it).second)
std::cout << *it << " ";
}
return 0;
}
Prints:
1 2 3 4
I will try to explain how this works:
The original array is iterated from start to finish (BTW as you can see it can be any length, not just 10, as it uses iterators of beginning and end)
We are going to store duplicates which we find with std::count in std::set
We count from current iterator until the end of the array for efficiency
When count > 1, this means we have a duplicate so we store it in set for reference.
std::set has unique keys, so trying to store another number that already exists in set will result in insert .second returning false.
Hence, we print only unique insertions, which appear to be in the order of elements appearing in the array.
In your case you can use class std::vector which allows you to Erase elements, resize the array...
Here is an example I provide which produces what you wanted:
1: Push the values into a vector.
2: Use 2 loops and compare the elements array[i] and array[j] and if they are identical push the the element j into a new vector. Index j is always equal to i + 1 in order to avoid comparing the value with itself.
3- Now you get a vector of the repeated values in the temporary vector; You use 2 loops and search for the repeated values and erase them from the vector.
4- Print the output.
NB: I overloaded the insertion operator "<<" to print a vector to avoid each time using a loop to print a vector's elements.
The code could look like :
#include <iostream>
#include <vector>
std::ostream& operator << (std::ostream& out, std::vector<int> vecInt){
for(int i(0); i < vecInt.size(); i++)
out << vecInt[i] << ", ";
return out;
}
int main() {
std::vector< int > vecInt;
//1 1 1 1 2 2 2 3 3 4
vecInt.push_back(1);
vecInt.push_back(1);
vecInt.push_back(1);
vecInt.push_back(1);
vecInt.push_back(2);
vecInt.push_back(2);
vecInt.push_back(2);
vecInt.push_back(3);
vecInt.push_back(3);
vecInt.push_back(4);
std::vector<int> vecUniq;
for(int i(0); i < vecInt.size(); i++)
for(int j(i + 1); j < vecInt.size(); j++)
if(vecInt[i] == vecInt[j])
vecUniq.push_back(vecInt[j]);
std::cout << vecUniq << std::endl;
for(int i = 0; i < vecUniq.size(); i++)
for(int j = vecUniq.size() - 1 ; j >= 0 && j > i; j--)
if(vecUniq[i] == vecUniq[j])
vecUniq.erase(&vecUniq[j]);
std::cout << vecUniq << std::endl;
std::cout << std::endl;
return 0;
}
The input: 1 2 3 3 4 5 6 7 8 9
The output: 3
The input: 1 2 3 4 1 2 3 4 5 6
The output: 1 2 3 4
The input: 1 1 1 1 2 2 2 3 3 4
The output: 1 2 3
For this problem, you can use a marking array that will count the number of times you a digit is visited by you, it's just like counting sort. let's first see the program :
#include <iostream>
using namespace std;
int print(int a[],int b[])
{
cout<<"b :: ";
for (int index=0;index<10;index++)
{
cout<<b[index]<<" ";
}
cout<<endl;
}
int main ()
{
int a[10],b[11], index, checker, common;
for (index=0; index<10; index++)
{
cin >> a [index];
b[index] = 0;
}
b[10] =0;
for (index=0;index<10;index++)
{
b[a[index]]++;
if (b[a[index]] == 2)
cout<<a[index];
//print(a,b);
}
return 0;
}
As you can see that I have used array b as marking array which counts the time a number is visited.
The size of array b depends upon what is the largest number you are going to enter, I have set the size of array b to be of length 10 that b[11] as your largest number is 10. Index 0 is of no use but you need not worry about it as it will be not pointed until your input has 0.
Intially all elements in array in b is set 0.
Now assume your input to be :: 1 2 3 4 1 2 3 4 5 6
Now value of b can be checked after each iteration by uncommenting the print function line::
b :: 0 1 0 0 0 0 0 0 0 0 ....1
b :: 0 1 1 0 0 0 0 0 0 0 ....2
b :: 0 1 1 1 0 0 0 0 0 0 ....3
b :: 0 1 1 1 1 0 0 0 0 0 ....4
b :: 0 2 1 1 1 0 0 0 0 0 ....5
b :: 0 2 2 1 1 0 0 0 0 0 ....6
b :: 0 2 2 2 1 0 0 0 0 0 ....7
b :: 0 2 2 2 2 0 0 0 0 0 ....8
b :: 0 2 2 2 2 1 0 0 0 0 ....9
b :: 0 2 2 2 2 1 1 0 0 0 ....10
In line 5 you can b's at index 1 has value 2 so it will print 1 that is a[index].
And array a's element will be printed only when it is repeated first time due to this line if(b[a[index]] == 2) .
This program uses the idea of counting sort so if you want you can check counting sort.

Generate a pattern for i-th order partial derivative in d-dimension

I am trying to work out a finite element code, where I need to compute the partial derivatives in d dimension. In finite element the basis function N(x,y,z)=N(x)N(y)N(z), so the first order derivatives are:
N(x)'N(y)N(z) N(x)N(y)'N(z) N(x)N(y)N(z)'
second order derivatives are
N(x)''N(y)N(z) N(x)'N(y)'N(z) N(x)'N(y)N(z)' N(x)N(y)''N(z) N(x)N(y)N(z)' N(x)N(y)N(z)''
I want to have a functions with input (i,d) to tell me these patterns in the table below:
I think there must be a simple algorithm to realize this goal. Can someone gives me some help? THx
This can be solved with nested loops:
int * part_deriv(int i, int d){
int *res;
int *curr;
int num_el = fact(i+d-1) / ( fact(i) * fact(d-1) ); //fact() is the factorial function
int el_size = d*sizeof(int);
int el;
res = calloc(num_el,el_size);
curr = calloc(d,sizeof(int));
*curr = i;
memcpy(res,curr,el_size); //put the first element in the array
el = 0;
while(el<num_el){
if(*curr != 0){
for( d_idx = 1 ; d_idx<d ; d_idx++, *cur++){
*curr--; // "move" one derivative from the first variable to 'd_idx' variable
*(curr+d_idx)++;
el++;
memcpy(res+(el*el_size),curr,el_size); //put the element in the array
}
*curr--;
} else{
break; //shouldn't be reached, but added to be sure
}
}
return res;
}
I havn't completely understood how you want to output the result, so you can parse the array I output in blocks of d.
Consider the pattern for i'th derivative as base-i+1 integers. Nice sequences emerge. For example, in a two-dimensional case, they are
0
2, 1
6, 4, 2
12, 9, 6, 3
20, 16, 12, 8, 4
etc.
I realized it by recursive by calling a function.
#include <vector>
#include <iostream>
using namespace std;
void func (int d, int i, vector<int> &k, int n, int start, vector<vector<int>> &a){
if (n==i)
{
vector<int> m;
int it=0;
for(int it1=0;it1<d;++it1){
int amount=0;
while(find(k.begin(),k.end(),it)!= k.end()){
amount++;
it++;
}
m.push_back(amount);
it++;
}
a.push_back(m);
}
else{
for(int jj=start;jj<d+i-(i-n);++jj){
k[n]=jj;
func(d,i,k,n+1,jj+1, a
);
}
}
}
vector<vector<int>> test(int d, int i){
vector<int> kk(i);
vector<vector<int>> a;
func(d,i,kk,0,0, a);
return a;
}
int main(){
auto f = test(4,2);
for(auto it1=f.begin();it1!=f.end();++it1){
for(auto it2= it1->begin();it2!=it1->end();++it2)
cout<<*it2<<" ";
cout<<endl;
}
}
Here is my result for i=2,d=4:
2 0 0 0
1 1 0 0
1 0 1 0
1 0 0 1
0 2 0 0
0 1 1 0
0 1 0 1
0 0 2 0
0 0 1 1
0 0 0 2

Brute Force Permutation Swapping

I've been working on a brute force algorithm to generate all permutations of a given set. Eventually, I want to feed each of these permutations into a nxn matrix to test if it is a valid magic square or not.
--I KNOW THAT THERE IS A WAY TO GENERATE A MAGIC SQUARE EASILY--
That is not what I want to do, though. I'm focusing on the brute force aspect of it.
For a set of 3 elements, it works wonderfully. However, once I use 4 or more elements, I lose out on a few permutations. Just from looking at the output of 4, I am missing 7 permutations.
#include <stdio.h>
#include <iostream>
using namespace std;
//ms = magic square
//n = size
void perm(int ms[], int n) {
int pivot = 0;
int index = 0;
int pivBit = 1;
int fin = 0;
int hold = 0;
//While we are not finished
while (fin == 0) {
//Incriment the index
++index;
if (index >= n) {
index = 0;
}
//if index is equal to the pivot
if (index == pivot) {
//Is this the first time visiting the pivot?
if (pivBit == 0) {
//Are we at the beginning again?
if (index == 0 && pivot == 0)
{
fin = 1;
}
pivBit = 1;
++index;
}
//Second time visiting?
else {
pivBit = 0;
++pivot;
if (pivot >= n) {
pivot = 0;
}
}
}
//If we are out of bounds
if (index >= n) {
index = 0;
}
//swap
hold = ms[index];
ms[index] = ms[pivot];
ms[pivot] = hold;
for (int i = 0; i < n; ++i) {
cout << ms[i];
if (i < n - 1) {
cout << ", ";
}
else {
cout << endl;
}
}
}
}
int main() {
cout << "Are you ready to brute force, my brother?" << endl;
//Set
int magicsquare[] = { 1, 2, 3, 4};
int size = 4;
perm(magicsquare, size);
getchar();
return 0;
}
My output is:
2 1 3 4
3 1 2 4
4 1 2 3
1 4 2 3
1 2 4 3
1 3 4 2
3 1 4 2
3 4 1 2
3 4 2 1
2 4 3 1
2 3 4 1
2 3 1 4
4 3 1 2
4 2 1 3
4 2 3 1
1 2 3 4
2 1 3 4
Looking at it, I can already see that I am missing both 1 4 3 2 and 1 3 2 4.
Where've I gone wrong in my algorithm?
The wiki article on permutation includes a common algorithm used to produce all permutations in lexicographic order, starting with an array of sequentially increasing integers, ending with that array reversed. wiki next permutation.
If dealing with an array of objects, you can generate an array of indices 0 through n-1 and use next permutation on the indices to produce all permutations of the array of objects.
You can also do a web search for next permutation to find similar algorithms. The recursive ones produce all permutations, but not in lexicographic order.
The simplest way to generate all permutations is recursive. For each i, swap the i'th element to the 0 position. Then recursively find all permutations of of the remaining array.
int buf[1000], n; // better to wrap these in a class...
void permute(int *a, int a_len) {
if (a_len == 1) {
for (int i = 0; i < n; i++) printf("%d ", buf[i]);
printf("\n");
} else {
for (int i = 0; i < a_len; i++) {
swap(a, 0, i);
permute(a + 1, a_len - 1);
swap(a, 0, i);
}
}
}
void run(int buf_len) {
for (int i = 0; i < buf_len; i++) buf[i] = i + 1;
n = buf_len;
permute(buf, buf_len);
}
This assumes no repeated elements in the original array. It's not to hard to have it take repeated elements into account.

Nested for loops recursion

I looked up in many places and tried to understand how to get arbitrary number of nested for loops via recursion. But what I have understood is clearly wrong.
I need to generate coordinates in an n-dimensional space, in a grid-pattern. The actual problem has different coordinates with different ranges, but to get simpler things right first, I have used the same, integer-stepped coordinate ranges in the code below.
#include <iostream>
using namespace std;
void recursion(int n);
int main(){
recursion(3);
return 0;
}
void recursion(int n)
{
if(n!=0){
for(int x=1; x<4; x++){
cout<<x<<" ";
recursion(n-1);
}
}
else cout<<endl;
}
I want, and was expecting the output to be:
1 1 1
1 1 2
1 1 3
1 2 1
1 2 2
1 2 3
1 3 1
1 3 2
1 3 3
2 1 1
2 1 2
2 1 3
2 2 1
2 2 2
2 2 3
2 3 1
2 3 2
2 3 3
3 1 1
3 1 2
3 1 3
3 2 1
3 2 2
3 2 3
3 3 1
3 3 2
3 3 3
Instead, the output I'm getting is
1 1 1
2
3
2 1
2
3
3 1
2
3
2 1 1
2
3
2 1
2
3
3 1
2
3
3 1 1
2
3
2 1
2
3
3 1
2
3
I just can't figure out whats wrong. Any help to figure out the mistake or even another way to generate coordinates will be greatly appreciated. Thanks!
Non-recursive solution based on add-with-carry:
#include <iostream>
using namespace std;
bool addOne(int* indices, int n, int ceiling) {
for (int i = 0; i < n; ++i) {
if (++indices[i] <= ceiling) {
return true;
}
indices[i] = 1;
}
return false;
}
void printIndices(int* indices, int n) {
for (int i = n-1; i >= 0; --i) {
cout << indices[i] << ' ';
}
cout << '\n';
}
int main() {
int indices[3];
for (int i=0; i < 3; ++i) {
indices[i] = 1;
}
do {
printIndices(indices, 3);
} while (addOne(indices, 3, 3));
return 0;
}
Recursive solution, salvaged from your original code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
void recursion(int n, const string& prefix);
int main(){
recursion(3, "");
return 0;
}
void recursion(int n, const string& prefix)
{
if (n!=0) {
for(int x=1; x<4; x++){
ostringstream os;
os << prefix << x << ' ';
recursion(n-1, os.str());
}
}
else cout << prefix << endl;
}
Per Igor's comment, you need an increment function.
Let's use an std::vector to represent each dimension. That is vector[0] is the first dimension, vector[1] is the second dimension and so on.
Using a vector allows us to determine the number of dimensions without any hard coded numbers. The vector.size() will be the number of dimensions.
Here is a function to get you started:
void Increment_Coordinate(std::vector<int>& coordinates,
int max_digit_value,
int min_digit_value)
{
unsigned int digit_index = 0;
bool apply_carry = false;
do
{
apply_carry = false;
coordinates[digit_index]++; // Increment the value in a dimension.
if (coordinates[digit_index] > max_digit_value)
{
// Reset the present dimension value
coordinates[digit_index] = min_digit_value;
// Apply carry to next column by moving to the next dimension.
++digit_index;
apply_carry = true;
}
} while (apply_carry);
return;
}
Edit 1
This is only a foundation. The function needs to be boundary checked.
This function does not support dimensions of varying sizes. That is left as an exercise for reader or OP.