This question already exists:
Recursion all combinations of lower triangle C++
Closed 8 years ago.
I recently posted a poor question on how to use recursion to estimate all combinations of lower triangle in C++. I managed to find a recursive algorithm that given an array of size n, generates and prints all possible combinations of r elements in array. I've employed this function using Rcpp in R. I've then written a loop around this function to get all the subsets of combinations r to r + n.
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
int recursive(IntegerVector arr, IntegerVector data, int start, int end, int index, int r)
{
if (index == r)
{
for (int j=0; j<r; j++)
printf("%d ", data[j]);
printf("\n");
}
for (int i=start; i<=end && end-i+1 >= r-index; i++)
{
data[index] = arr[i];
recursive(arr, data, i+1, end, index+1, r);
}
}
R code with five groups:
Rcpp::sourceCpp('recursive2.cpp')
nComm <- 5
r <- c(2:nComm)
n <- nComm
arr <- c(1:nComm)
dat <- c(1:nComm)
for(i in 1:(n-1)){
recursive(arr, dat, 0, n-1, 0, r[i])
}
1 2
1 3
1 4
1 5
2 3
2 4
2 5
3 4
3 5
4 5
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
1 2 3 4
1 2 3 5
1 2 4 5
1 3 4 5
2 3 4 5
1 2 3 4 5
Currently, this just prints the subsets of combinations I need to estimate my dissimilarities. I'd like to be able to remove the loop and use it as a single Rcpp function/script. With the end goal to be able to use the subsets (currently printed combinations) as way to subset rows in an array. Which will be used to calculate the intersect between vectors. So 1 2 will be used to compare rows 1 and 2 in an array. And so forth.
Related
Given a subset of nodes {1,2,...,N} is there any STL or boost function that returns unique undirected tours over all of them?
std::next_permutation() gives all N! directed tours, where 1-2-...-N is different from N-N-1-...-2-1.
However, in this case, I don't want both of them, but only one of them. Essentially, I would like to enumerate only N! / 2 of the tours.
The following code that uses std::next_permutation() and unordered_set works, but is there anything more efficient? The following code essentially generates all N! directed tours and discards half of them after checking against an unordered_set().
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <boost/functional/hash.hpp>
template <typename T, typename U> bool unorderedset_val_there_already_add_if_not(std::unordered_set<T, U>& uos, T& val) {
if (uos.find(val) != uos.end())
return true;//val already there
uos.insert(val);
return false;//Value is new.
}
int main() {
std::vector<int> sequence{ 1, 2, 3};
std::unordered_set<std::vector<int>, boost::hash<std::vector<int>>> uos;
do {
printf("Considering ");
for (std::size_t i = 0; i < sequence.size(); i++)
printf("%d ", sequence[i]);
printf("\n");
std::vector<int> rev_sequence = sequence;
std::reverse(rev_sequence.begin(), rev_sequence.end());
if (unorderedset_val_there_already_add_if_not(uos, sequence) || unorderedset_val_there_already_add_if_not(uos, rev_sequence)) {
printf("Already there by itself or its reverse.\n");
}
else {
printf("Sequence and its reverse are new.\n");
}
} while (std::next_permutation(sequence.begin(), sequence.end()));
getchar();
}
That is, given {1,2,3}, I only want to enumerate (1-2-3), (1-3-2) and (2-1-3). The other three permutations (2-3-1), (3-1-2) and (3-2-1) should not be enumerated because their reverse sequence have already been enumerated.
If you want to stay with next_permutation rather than make own generator routine, the simplest way is filter out a half of permutation with some condition.
Very simple one: the last element should be larger than the first one.
#include <vector>
#include <algorithm>
#include "stdio.h"
int main() {
std::vector<int> sequence{ 1, 2, 3, 4};
do {
if (sequence[sequence.size()-1] > sequence[0]) {
for (std::size_t i = 0; i < sequence.size(); i++)
printf("%d ", sequence[i]);
printf("\n");
}
} while (std::next_permutation(sequence.begin(), sequence.end()));
getchar();
}
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 4 1 3
3 1 2 4
3 2 1 4
Possible own implementation:
Generate all pairs (start; end) where start < end
Generate all permutations of `n-2` values without start and end
For every permutation make {start, permutation.., end}
1 ... 2 + permutations of {3, 4}
1 3 4 2
1 4 3 2
1 ... 3 + permutations of {2,4}
1 2 4 3
1 4 2 3
...
3 ... 4 + permutations of {1, 2}
3 1 2 4
3 2 1 4
...
OK I am trying to make Prima algorithm so i need my edges array sorted, I tried to use quicksort here but it didn't work as I planned.
#include <iostream>
using namespace std;
void Sort (int arr[100][4], int m, int l) {
int i,j,x,v;
i=m;
j=l;
x=(i+j)/2;
do
{
while (((arr[i][3]<arr[x][3]))and(i<=l)) i++;
while (((arr[j][3]>arr[x][3]))and(j>=m)) j--;
if (i<=j)
{
v=arr[i][1];
arr[i][1]=arr[j][1];
arr[j][1]=v;
v=arr[i][2];
arr[i][2]=arr[j][2];
arr[j][2]=v;
v=arr[i][3];
arr[i][3]=arr[j][3];
arr[j][3]=v;
i++;
j--;
}
}
while (i<=j);
if (i<l) Sort(arr,i,l);
if (m<j) Sort(arr,m,j);
}
int main () {
int i,x,y,z,n,m;
int a[100][4];
fill(&a[0][0],&a[0][0]+400,0);
cout<<"Enter number of nodes and edges\n";
cin>>n>>m;
cout<<"Enter edges and their weights\n";
for (i=0;i<m;i++) {
cin>>x>>y>>z;
a[i][1]=min(x,y);
a[i][2]=max(x,y);
a[i][3]=z;
}
Sort (a,0,m-1);
for (i=0;i<m;i++) {
cout<<i+1<<") "<<a[i][1]<<' '<<a[i][2]<<' '<<a[i][3]<<endl;
}
return 0;
}
what I put is
5 10
1 2 4
1 3 7
4 1 5
5 1 8
2 3 3
2 4 6
2 5 6
3 4 8
3 5 2
4 5 4
what I get is
1) 3 5 2
2) 2 3 3
3) 1 4 5
4) 1 2 4
5) 4 5 4
6) 2 5 6
7) 2 4 6
8) 1 3 7
9) 1 5 8
10) 3 4 8
I don't understand why 5 is going ahead of 4's. Hope you could help.
You choose the pivot element in the middle of the (sub)array, which is fine, but you leave it in that position when you run the partitioning loop, and rely on it to stay there, which is not ok. With your approach, the pivot is likely to be swapped to a different position during the ordinary course of partitioning, after which the remainder of the partitioning will be based on the key swapped into the pivot's original position, which is likely to be different.
The usual approach is to start by swapping the pivot element to one end of the array or the other, partition the rest of the array, and then afterward swap the pivot into its correct position, as discovered via the partitioning process.
Change the code to use the pivot value instead of the pivot index, and some fixes to make it more like conventional Hoare partition scheme:
i=m-1;
j=l+1;
x=arr[(i+j)/2][3];
while(1)
{
while (arr[++i][3] < x);
while (arr[--j][3] > x);
if(i >= j)
return j;
// ...
Having difficulty finding an explanation to this.
What does this code do? I understand it creates an array of vector but that's about it.
How can I print the vector array and access elements to experiment with it?
#define MAXN 300009
vector<int>dv[MAXN];
int main()
{
for(int i=1;i<MAXN;i++)
for(int j=i;j<MAXN;j+=i)
dv[j].push_back(i);
}
The code is easy enough to instrument. The reality of what it ends up producing is a very simple (and very inefficient) Sieve of Eratosthenes. Understanding that algorithm, you'll see what this code does to produce that ilk.
Edit: It is also a factor-table generator. See Edit below.
Instrumenting the code and dumping output afterward, and reducing the number of loops for simplification we have something like the following code. We use range-based-for loops for enumerating over each vector in the array of vectors:
#include <iostream>
#include <vector>
#define MAXN 20
std::vector<int>dv[MAXN];
int main()
{
for(int i=1;i<MAXN;i++)
{
for(int j=i;j<MAXN;j+=i)
dv[j].push_back(i);
}
for (auto const& v : dv)
{
for (auto x : v)
std::cout << x << ' ';
std::cout << '\n';
}
}
The resulting output is:
1
1 2
1 3
1 2 4
1 5
1 2 3 6
1 7
1 2 4 8
1 3 9
1 2 5 10
1 11
1 2 3 4 6 12
1 13
1 2 7 14
1 3 5 15
1 2 4 8 16
1 17
1 2 3 6 9 18
1 19
Now, note each vector that only has two elements (1 and an additional number). That second number is prime. In our test case those two-element vectors are:
1 2
1 3
1 5
1 7
1 11
1 13
1 17
1 19
In short, this is a very simple, and incredibly inefficient way of finding prime numbers. A slight change to the output loops to only output the second element of all vectors of length-two-only will therefore generate all the primes lower than MAXN. Therefore, using:
for (auto const& v : dv)
{
if (v.size() == 2)
std::cout << v[1] << '\n';
}
We will get all primes from [2...MAXN)
Edit: Factor Table Generation
If it wasn't obvious, each vector has an ending element (that not-coincidentally also lines up with the subscripts of the outer array). All preceding elements make up the positive factors of that number. For example:
1 2 5 10
is the dv[10] vector, and tells you 10 has factors 1,2,5,10. Likewise,
1 2 3 6 9 18
is the dv[18] vector, and tells you 18 has factors 1,2,3,6,9,18.
In short, if someone wanted to know all the factors of some number N that is < MAXN, this would be a way of putting all that info into tabular form.
I am given this problem:
We are going over recursion in my class and I do not quite understand it, I was wondering if someone can help me with this problem
let c(n) be the number of different group integers that can be chosen from the integers 1 through n-1, so that the integers in each group add up to n (for example, n=4=[1+1+1+1]=[1+1+2]=[2+2]). Write a recursive definition for c(n) under the following variations:
a) You count permutations. For example, 1,2,1 and 1,1,2 are two groups that each add up to 4
b)you ignore permutations
I know permutations is how many ways you can arrange a set of numbers, so is my code below correct? I get an answer of 7?
Here is my code for part a:
int recurse (int n);
int main(){
int a=4;
int sum_perm;
sum_perm=recurse(a);
cout<<sum_perm-1<<endl;
//Can I do -1 here because it should be from a group of integers from 1 to n-1?
return 0;
}
int recurse(int n)
{
int sum = 1;
if (n == 1){
return 1;
}
for(int i = 1; i < n; i++){
sum += recurse(n - i);
}
return sum;
}
For part B, if I am not counting permutations, what am I counting?
Here is my code for part b:
int without (int n, int max);
int main(){
int a=4, b =3;
int sum_without;
sum_without=without(a,b);
cout<<sum_without<<endl;
system("Pause");
return 0;
}
int without(int n, int max)
{
if(n == 1 || max == 1){
return 1;
}
else if (n == max){
return 1 + without(n, n-1);
}
else{
return without(n,max-1) + without(n-max, max);
}
}
You don't show any code to generate the combinations of numbers that produce a sum. Link to wiki article about partitions .
In this case, the goal is to count the number of combinations and/or permutations, which might be possible without actually generating a set of combinations. Not sure if recursion helps here, but you can convert any loop into recursion if you pass enough variables.
Example "partitions"
1 combination that sums to 1:
1
2 combinations that sum to 2:
1 1
2
3 combinations that sum to 3:
1 1 1
1 2
3
5 combinations that sum to 4:
1 1 1 1
1 1 2
1 3
2 2
4
7 combinations that sum to 5:
1 1 1 1 1
1 1 1 2
1 1 3
1 2 2
1 4
2 3
5
11 combinations of numbers that sum to 6:
1 1 1 1 1 1
1 1 1 1 2
1 1 1 3
1 1 2 2
1 1 4
1 2 3
2 2 2
1 5
2 4
3 3
6
I would recommend combinations directly being considered. While it seems like the more difficult case a simple rule makes it trivial.
Numbers calculated are in decreasing order
This requires you to track the last number, but ensures you don't calculate 1 5 and then 5 1, as the former is impossible.
The first one is straightforward, just walk from both sides until finding a reversion.
/*C++ version, [first, last), last needs --first to fetch the last element*/
/*returns the middle of partitioning result*/
int* partition( int *first, int *last, int pivot ) {
while (true) {
while (*first < pivot) ++first;
--last;//Don't edit this, it's true.
while (pivot < *last) --last;
if (!(first < last)) return first;
swap(*first, *last);
++first;
}
}
The second one (shown in "Introduction to algorithms") is:
int* partition( int a[], int n, int pivot ) {
bound = 0;
for ( i = 1; i != n; ++i )
if ( a[i] < pivot )
swap( &a[i], &a[++bound]);
swap(a, a + bound);
return a + bound;
}
The invariant of the second one is " All elements before bound is less than pivot " .
Q: And what is the advantages and disadvantages of the two versions?
I'll give one first, the second one require ++ operation on the iterator( pointer ), so it can be applied to some ForwardIterator like the iterator of a linked list. Other tips?
As far as the basic idea of the two algorithms go, both are correct. They will do the same number of comparisons but the second one will do more swaps than the first.
You can see this by stepping through the algorithms as they partition the array 1 9 2 8 3 7 4 6 5 using 5 as the pivot. When the first algorithm swaps two numbers it never touches either of then again. The second algorithm first swaps 9 and 2, then 9 and 3, and so on, taking multiple swaps to move 9 to its final position.
There are other differences too. If I haven't made any mistakes, this is how the first algorithm partitions the array:
1 9 2 8 3 7 4 6 5
f l
1 9 2 8 3 7 4 6 5 # swap 9,5
f l
1 5 2 8 3 7 4 6 9 # swap 8,4
f l
1 5 2 4 3 7 8 6 9 # return f = 5
l f
This is how the second algorithm partitions the array:
1 9 2 8 3 7 4 6 5 # 1<5, swap 1,1
bi
1 9 2 8 3 7 4 6 5 # 9>5, no swap
bi
1 9 2 8 3 7 4 6 5 # 2<5, swap 9,2
b i
1 2 9 8 3 7 4 6 5 # 8>5, no swap
b i
1 2 9 8 3 7 4 6 5 # 3<5, swap 9,3
b i
1 2 3 8 9 7 4 6 5 # 7>5, no swap
b i
1 2 3 8 9 7 4 6 5 # 4<5, swap 8,4
b i
1 2 3 4 9 7 8 6 5 # 6>5, no swap
b i
1 2 3 4 9 7 8 6 5 # 5=5, exit loop, swap 9,5
b i
1 2 3 4 5 7 8 6 9 # return b = 4
b i
Notice how it makes 5 swaps, compared to just 2 of the other algorithm. It also moves the last item in the array to the middle array. In this case the last item happens to be the pivot so it's the pivot that's moved to the middle, but that's not the general case.