Observe the following code:
#include <vector>
#include <iostream>
#include <string>
template <typename T>
void print_2d_vector(std::vector<std::vector<T>>& v)
{
for(int i = 0; i < v.size(); i++)
{
std::cout << "{";
for(int j = 0; j < v[i].size(); j++)
{
std::cout << v[i][j];
if(j != v[i].size() - 1)
{
std::cout << ", ";
}
}
std::cout << "}\n";
}
}
template <typename T>
struct permcomb2
{
std::vector<std::vector<T>> end_set;
std::vector<T>* data;
permcomb2(std::vector<T>& param) : data(¶m) {}
void helpfunc(std::vector<T>& seen, int depth)
{
if(depth == 0)
{
end_set.push_back(seen);
}
else
{
for(int i = 0; i < (*data).size(); i++)
{
seen.push_back((*data)[i]);
helpfunc(seen, depth - 1);
seen.pop_back();
}
}
}
};
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size)
{
permcomb2<T> helpstruct(data);
std::vector<T> empty {};
helpstruct.helpfunc(empty, subset_size);
return helpstruct.end_set;
}
using namespace std;
int main()
{
std::vector<std::string> flavors {"Vanilla", "Chocolate", "Strawberry"};
auto a1 = permtest(flavors, 2);
cout << "Return all combinations with repetition\n";
print_2d_vector(a1);
return 0;
}
Running this code results in the following output:
Return all combinations with repetition
{Vanilla, Vanilla}
{Vanilla, Chocolate}
{Vanilla, Strawberry}
{Chocolate, Vanilla}
{Chocolate, Chocolate}
{Chocolate, Strawberry}
{Strawberry, Vanilla}
{Strawberry, Chocolate}
{Strawberry, Strawberry}
Notice how this code does NOT do what it claims to do! Instead of returning all combinations with repetition of a given subset size (the goal), it instead returns all permutations with repetition of a given subset size. Of course, a way to obtain the combinations would be to generate all of the permutations as I have done, and then loop through to remove all but one of those which are permutations of each other. But I'm confident that this is absolutely NOT the most efficient way to do this.
I've seen ways which use nested for loops to achieve this, but those assume that the subset size is known ahead of time. I'm trying to generalize it for any subset size, hence why I'm trying to do it recursively. The issue is that I'm not quite sure how I need to change my recursive "helpfunc" in order to generate all of the combinations in a way that's efficient.
Just to clarify, the expected output would be this:
Return all combinations with repetition
{Vanilla, Vanilla}
{Vanilla, Chocolate}
{Vanilla, Strawberry}
{Chocolate, Chocolate}
{Chocolate, Strawberry}
{Strawberry, Strawberry}
So how can I change my code to obtain all combinations with repetition instead of the permutations in a way that's efficient?
Make sure the helpfunc loop starts from the index we are on and only considers the ones in front. The ones behind we don't want since they will only be duplicates.
#include <vector>
#include <iostream>
#include <string>
template <typename T>
void print_2d_vector(std::vector<std::vector<T>>& v)
{
for(int i = 0; i < v.size(); i++)
{
std::cout << "{";
for(int j = 0; j < v[i].size(); j++)
{
std::cout << v[i][j];
if(j != v[i].size() - 1)
{
sizetd::cout << ", ";
}
}
std::cout << "}\n";
}
}
template <typename T>
struct permcomb2
{
std::vector<std::vector<T>> end_set;
std::vector<T>& data;
permcomb2(std::vector<T>& param) : data(param) {}
void helpfunc(std::vector<T>& seen, int depth, int current) // Add one more param for the starting depth of our recursive calls
{
if(depth == 0)
{
end_set.push_back(seen);
}
else
{
for(int i = current; i < data.size(); i++) // Set the loop to start at given value
{
seen.push_back(data[i]);
helpfunc(seen, depth - 1, i);
seen.pop_back();
}
}
}
};
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size)
{
permcomb2<T> helpstruct(data);
std::vector<T> empty {};
helpstruct.helpfunc(empty, subset_size, 0); // Initialize the function at depth 0
return helpstruct.end_set;
}
using namespace std;
int main()
{
std::vector<std::string> flavors {"Vanilla", "Chocolate", "Strawberry"};
auto a1 = permtest(flavors, 2);
cout << "Return all combinations with repetition\n";
print_2d_vector(a1);
return 0;
}
You can think about solving this problem by having nested for loops, where each loop's counter goes from the previous index to the data size.
for (int i = 0; i < data.size(); i++) {
for (int j = i; j < data.size(); j++) {
for (int k = j; k < data.size(); k++) {
// etc...
}
}
The trouble is that the depth of loop-nesting is equal to subset_size. We can simulate this arbitrary-depth nesting by having a recursive call in a loop:
template <class T>
void solution(std::vector<T>& data, std::vector<std::vector<T>>& sol, int subset_size, int start=0, int depth=0) {
if (depth == subset_size) return;
// Assume that the last element of sol is a base vector
// on which to append the data elements after "start"
std::vector<T> base = sol.back();
// create (data.size() - start) number of vectors, each of which is the base vector (above)
// plus each element of the data after the specified starting index
for (int i = start; i < data.size(); ++i) {
sol.back().push_back(data[i]); // Append i'th data element to base
solution(data, sol, subset_size, i, depth + 1); // Recurse, extending the new base
if (i < data.size() - 1) sol.push_back(base); // Append another base for the next iteration
}
}
template <typename T>
std::vector<std::vector<T>> permtest(std::vector<T>& data, int subset_size) {
std::vector<std::vector<T>> solution_set;
solution_set.push_back(std::vector<T>());
solution(data, solution_set, subset_size);
return solution_set;
}
Related
I'm trying to make a generic function which will dynamically allocate 2D structure. Number of elements in every row doesn't have to be same for all rows. Structure is represented as a container type, whose elements are again of a container type (for example a set of lists). The type of elements of that inner container can also be arbitrary. Containers only support the begin, end, and size functions. Iterator operations must be supported for all iterator types. The function should first dynamically allocate the space for storing the 2D structure by the continuous allocation procedure, and then rewrite the elements of the structure it has accepted into the dynamic structure. The function returns a double pointer through which the elements of this structure can be accessed.
#include <iostream>
#include <set>
#include <list>
#include <vector>
template < typename tip >
auto Make2DStructure(tip mat) {
using tip_objekta = typename std::decay < decltype(mat[0][0]) > ::type;
tip_objekta ** dynamic_mat = nullptr;
int rows = 0, total = 0;
for (auto i: mat) {
rows++;
for (auto j: i)
total++;
}
int columns[rows];
int k = 0;
for (auto i: mat) {
int num_of_colums = 0;
for (auto j: i)
num_of_colums++;
columns[k] = num_of_colums;
k++;
}
try {
dynamic_mat = new tip_objekta * [rows];
dynamic_mat[0] = new tip_objekta[total];
for (int i = 1; i < rows; i++)
dynamic_mat[i] = dynamic_mat[i - 1] + columns[i];
for (int i = 0; i < rows; i++)
for (int j = 0; j < columns[i]; j++)
dynamic_mat[i][j] = mat[i][j];
} catch (...) {
delete[] dynamic_mat[0];
delete[] dynamic_mat;
throw std::bad_alloc();
}
return dynamic_mat;
}
int main() {
std::vector<std::vector<int>>mat{
{1,2},
{3,4,5,6},
{7,8,9}
};
int columns[3]={2,4,3};
try {
int ** dynamic_mat = Make2DStructure(mat);
for (int i = 0; i < 3; i++) {
for (int j = 0; j < columns[i]; j++)
std::cout << dynamic_mat[i][j] << " ";
std::cout << std::endl;
}
delete[] dynamic_mat[0];
delete[] dynamic_mat;
} catch (...) {
std::cout << "Problems with memory";
}
return 0;
}
How could I modify this to work without indexing inside Make2DStrucure()?
Also, if I used std::set<std::list<int>> instead of std::vector<std::vector<int>> in main function I would have deduction problems. How could I modify this to work for different outside and inside container?
Here's one way to accomplish what you want:
#include <iterator>
#include <type_traits>
template <typename tip>
auto Make2DStructure(tip&& mat) {
// create an alias for the value type:
using value_type = std::decay_t<decltype(*std::begin(*std::begin(mat)))>;
// allocate memory for the return value, the pointer-pointer:
value_type** rv = new value_type*[mat.size()]; // C++17: std::size(mat)
// Calculate the number of values we need to allocate space for:
size_t values = 0;
for(auto& inner: mat) values += inner.size(); // C++17: std::size(inner)
// allocate the space for the values:
value_type* data = new value_type[values];
// loop over the outer and inner container and keep the index running:
size_t idx = 0;
for(auto& inner : mat) {
// assign the outer pointer into the flat data block:
rv[idx++] = data;
for(auto& val : inner) {
// assign values in the data block:
*data++ = val;
}
}
return rv;
}
With the use of std::size where indicated, this would work with plain arrays too, not only the container classes.
I am a C++ student. And I need to solve this problem: "Write a program that receives a number and an array of the size of the given number. The program must find all the duplicates of the given numbers, push-back them to a vector of repeating elements, and print the vector". The requirements are I'm only allowed to use the vector library and every repeating element of the array must be pushed to the vector only once, e.g. my array is "1, 2, 1, 2, 3, 4...", the vector must be "1 ,2".
Here's what I've done so far. My code works, but I'm unable to make it add the same duplicate to the vector of repeating elements only once.
#include <iostream>
#include <vector>
int main() {
int n;
std::cin >> n;
int* arr = new int[n];
std::vector<int> repeatedElements;
for(int i = 0; i < n; ++i) {
std::cin >> arr[i];
}
for(int i = 0; i < n; ++i) {
bool foundInRepeated = false;
for(int j = 0; j < repeatedElements.size(); ++j) {
if(arr[i] == repeatedElements[j]) {
foundInRepeated = true;
break;
}
}
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) {
int count = 1;
for(int j = i + 1; j < n; ++j) {
if(arr[i] == arr[j]) {
++count;
}
}
if(count > 1) {
repeatedElements.push_back(arr[i]);
}
}
}
}
for(int i = 0; i < repeatedElements.size(); ++i) {
std::cout << repeatedElements[i] << " ";
}
std::cout << std::endl;
}
Consider what you're doing here:
if(foundInRepeated) {
continue;
} else {
for(int i = 0; i < n; ++i) { // why?
If the element at some index i (from the outer loop) is not found in repeatedElements, you're again iterating through the entire array, and adding elements that are repeated. But you already have an i that you're interested in, and hasn't been added to the repeatedElements. You only need to iterate through j in the else branch.
Removing the line marked why? (and the closing brace), will solve the problem. Here's a demo.
It's always good to follow a plan. Divide the bigger problem into a sequence of smaller problems is a good start. While this often does not yield an optimal solution, at least it yields a solution, which is more or less straightforward. And which subsequently can be optimized, if need be.
How to find out, if a number in the sequence has duplicates?
We could brute force this:
is_duplicate i = arr[i+1..arr.size() - 1] contains arr[i]
and then write ourselves a helper function like
bool range_contains(std::vector<int>::const_iterator first,
std::vector<int>::const_iterator last, int value) {
// ...
}
and use it in a simple
for (auto iter = arr.cbegin(); iter != arr.cend(); ++iter) {
if (range_contains(iter+1, arr.cend(), *iter) && !duplicates.contains(*iter)) {
duplicates.push_back(*iter);
}
}
But this would be - if I am not mistaken - some O(N^2) solution.
As we know, sorting is O(N log(N)) and if we sort our array first, we will
have all duplicates right next to each other. Then, we can iterate over the sorted array once (O(N)) and we are still cheaper than O(N^2). (O(N log(N)) + O(N) is still O(N log(N))).
1 2 1 2 3 4 => sort => 1 1 2 2 3 4
Eventually, while using what we have at our disposal, this could yield to a program like this:
#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>
using IntVec = std::vector<int>;
int main(int argc, const char *argv[]) {
IntVec arr; // aka: input array
IntVec duplicates;
size_t n = 0;
std::cin >> n;
// Read n integers from std::cin
std::generate_n(std::back_inserter(arr), n,
[](){
return *(std::istream_iterator<int>(std::cin));
});
// sort the array (in ascending order).
std::sort(arr.begin(), arr.end()); // O(N*logN)
auto current = arr.cbegin();
while(current != arr.cend()) {
// std::adjacent_find() finds the next location in arr, where 2 neighbors have the same value.
current = std::adjacent_find(current,arr.cend());
if( current != arr.cend()) {
duplicates.push_back(*current);
// skip all duplicates here
for( ; current != (arr.cend() - 1) && (*current == *(current+1)); current++) {
}
}
}
// print the duplicates to std::cout
std::copy(duplicates.cbegin(), duplicates.cend(),
std::ostream_iterator<int>(std::cout, " "));
return 0;
}
I need to output a group of letters that are that are out of order with respect to the number of inversions of each other.
For example, the sequence “AACEDGG” has only 1 inversion (E and D) while the sequence “ZWQM” has 6 inversions. I don't actually have to sort it out but I have to output them based on the number of inversions they have.
Ex:
Input: AACATGAAGG TTTTGGCCAA TTTGGCCAAA GATCAGATTT CCCGGGGGGA ATCGATGCAT
Output: CCCGGGGGGA AACATGAAGG GATCAGATTT ATCGATGCAT TTTTGGCCAA TTTGGCCAAA
I am trying to use insertion sort as a template as required by my teacher.
void inversionChecker(string dna[], int n)
{
int j,k,m;
int tempCount;
for(int i=0; i < n; i++){
int count=0;
for(j=0;j < n; j++){
for(k=j+1; k <= n; k++){
if(dna[i][j] > dna[i][k]){
count++;
tempCount = count;
}
}
}
if(i != 0 && tempCount > count)
dna[i].swap(dna[i-1]);
}
}
I am having issues because I am not too familiar using 2D arrays to compare the letters in each string. When I try to output the array it ends up being blank, seg faults, or errors resulting from my use trying to swap the positions of the strings in the array.
Any help would be appreciated
Here you access the dna array out-of-bounds:
for(j=0;j < n; j++){
for(k=j+1; k <= n; k++){ // when k == n you have undefined behavior
if(dna[i][j] > dna[i][k])
it should be:
for(j=0;j < n-1; j++){
for(k=j+1; k < n; k++){
if(dna[i][j] > dna[i][k])
An alternative approach using misc. standard classes and algorithms, like std::vector and std::sort.
#include <algorithm> // copy, sort
#include <cstddef> // size_t
#include <iterator> // istream_iterator, back_inserter
#include <sstream> // istringstream
#include <string> // string
#include <tuple> // tie
#include <utility> // swap
#include <vector> // vector
#include <iostream>
// count inversions in a sequence
unsigned count_inversions(std::string sequence) {
unsigned res = 0;
// assuming "inversions" are defined as the number of swaps needed in bubblesort
for(size_t i = 0; i < sequence.size() - 1; ++i) {
for(size_t j = i + 1; j < sequence.size(); ++j) {
if(sequence[j] < sequence[i]) {
std::swap(sequence[i], sequence[j]);
++res;
}
}
}
return res;
}
// a class to store a sequence and its inversion count
struct sequence_t {
sequence_t() = default;
explicit sequence_t(const std::string& Seq) :
seq(Seq), inversions(count_inversions(seq)) {}
// "less than" operator to compare two "sequence_t"s (used in std::sort)
bool operator<(const sequence_t& rhs) const {
// assuming lexicographical order if inversions are equal
return std::tie(inversions, seq) < std::tie(rhs.inversions, rhs.seq);
}
std::string seq;
unsigned inversions;
};
// read one sequence_t from an istream
std::istream& operator>>(std::istream& is, sequence_t& s) {
std::string tmp;
if(is >> tmp) s = sequence_t(tmp);
return is;
}
// read "sequence_t"s from an istream and put in a vector<sequence_t>
auto read_sequences(std::istream& is) {
std::vector<sequence_t> rv;
std::copy(std::istream_iterator<sequence_t>(is),
std::istream_iterator<sequence_t>{}, std::back_inserter(rv));
return rv;
}
int main() {
std::istringstream input(
"AACATGAAGG TTTTGGCCAA TTTGGCCAAA GATCAGATTT CCCGGGGGGA ATCGATGCAT");
auto sequences = read_sequences(input);
std::sort(sequences.begin(), sequences.end());
// print result
for(const auto& [seq, inversions] : sequences) {
std::cout << seq << '(' << inversions << ')' << ' ';
}
std::cout << '\n';
}
Output (including the inversions):
CCCGGGGGGA(2) AACATGAAGG(10) GATCAGATTT(10) ATCGATGCAT(11) TTTTGGCCAA(12) TTTGGCCAAA(15)
#include <iostream>
#include <cstdlib>
using std:: cin;
using std:: cout;
using std:: endl;
const int N=10;
void readarray(int array[], int N);
int bubble_sort (int array[], int size, int round,
int place);
int main ()
{
int array[N];
readarray( array, N );
int round, place;
cout << bubble_sort(array, N, place, round);
return EXIT_SUCCESS;
}
void readarray(int array[], int N)
{
int i=0;
if (i < N)
{
cin >> array[i];
readarray(array+1, N-1);
}
}
int bubble_sort (int array[], int size, int round,
int place)
{
round =0;
place =0;
if (round < N-1) // this goes over the array again making sure it has
// sorted from lowest to highest
{
if (place < N - round -1) // this sorts the array only 2 cells at a
// time
if (array[0] > array[1])
{
int temp = array[1];
array[1]=array[0];
array[0]=temp;
return (array+1, size-1, place+1, round);
}
return (array+1, size-1, place, round+1);
}
}
I know how to do a bubble sort using two for loops and I want to do it using recursion. Using loops you require two for loops and I figured for recursion it might also need two recursive functions/calls. This is what I have so far. The problem is that its outputting only one number, which is either 1 or 0. I'm not sure if my returns are correct.
In c++11, you can do this:
#include <iostream>
#include <vector>
void swap(std::vector<int &numbers, size_t i, size_t j)
{
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
bool bubble_once(std::vector<int> &numbers, size_t at)
{
if (at >= numbers.size() - 1)
return false;
bool bubbled = numbers[at] > numbers[at+1];
if (bubbled)
swap(numbers, at, at+1);
return bubbled or bubble_once(numbers, at + 1);
}
void bubble_sort(std::vector<int> &numbers)
{
if ( bubble_once(numbers, 0) )
bubble_sort(numbers);
}
int main() {
std::vector<int> numbers = {1,4,3,6,2,3,7,8,3};
bubble_sort(numbers);
for (size_t i=0; i != numbers.size(); ++i)
std::cout << numbers[i] << ' ';
}
In general you can replace each loop by a recursive function which:
check the guard -> if fail return.
else execute body
recursively call function, typically with an incremented counter or something.
However, to prevent a(n actual) stack overflow, avoiding recursion where loops are equally adequate is good practice. Moreover, a loop has a very canonical form and hence is easy to read for many programmers, whereas recursion can be done in many, and hence is harder to read, test and verify. Oh, and recursion is typically slower as it needs to create a new stackframe (citation needed, not too sure).
EDIT
Using a plain array:
#include <iostream>
#include <vector>
#define N 10
void swap(int *numbers, size_t i, size_t j)
{
int t = numbers[i];
numbers[i] = numbers[j];
numbers[j] = t;
}
bool bubble_once(int *numbers, size_t at)
{
if (at >= N - 1)
return false;
bool bubbled = numbers[at] > numbers[at+1];
if (bubbled)
swap(numbers, at, at+1);
return bubbled or bubble_once(numbers, at + 1);
}
void bubble_sort(int *numbers)
{
if ( bubble_once(numbers, 0) )
bubble_sort(numbers);
}
int main() {
int numbers[N] = {1,4,3,6,2,3,7,8,3,5};
bubble_sort(numbers);
for (size_t i=0; i != N; ++i)
std::cout << numbers[i] << ' ';
}
Please read this post
function pass(i,j,n,arr)
{
if(arr[i]>arr(j))
swap(arr[i],arr[j]);
if(j==n)
{
j=0;
i=i+1;
}
if(i==n+1)
return arr;
return pass(i,j+1,n,arr);
}
I need to implement a for_each function, like below. I know std::for_each could apply fn to each element, but we cannot erase elements in std::for_each. I need to extend this template function, so that in fn, the caller can both visit elements and erase elements one at a time. Is there a proper way to do this?
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class A
{
public:
explicit A(){
mVec.clear();
}
~A(){}
template<class T> void for_each(T fn)
{
for(size_t i = 0; i < mVec.size(); ++i)
{
//fn can erase element or just visit element
fn(mVec[i]);
}
}
vector<int> mVec;
};
int main()
{
A test;
for(int i = 0; i < 8; ++i)
{
test.mVec.push_back(i);
}
test.for_each([&test](int i){
if (i % 2 == 0)
{
cout << i << " deleted" << endl;
test.mVec.erase(find(test.mVec.begin(), test.mVec.end(), i));
}
else
{
cout << i << " parse" << endl;
}
});
system("pause");
return 0;
}
Edit: In for_each template function, we do not know whether the caller will erase elements or not. Erasing elements is done in fn
Could you return a bool value from the function, where true means "erase the element"? Then your for_each function becomes something like.
size_t i = 0;
for(size_t j = 0; j < mVec.size(); ++j) {
if (!fn(mVec[j])) {
// The element must be kept
if (i != j)
mVec[i] = std::move(mVec[j]);
i++;
}
}
mVec.resize(i);
The advantage is also that this is always O(n), no matter how many elements are erased.
EDIT: The loop above is really just std::remove_if(), so #ChenOT's suggestion is the best. Alternatively
n = std::remove_if(mVec.begin(), mVec.end(), fn) - mVec.begin();
mVec.resize(n);