how to implement a for_each like function in c++? - c++

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);

Related

Selection Sort Implementation with C++ incorrect

really new to C++, trying to instantiate some basic algorithms with it. Having trouble returning the correct result for selection sort. Here is my code
#include <iostream>
#include <array>
#include <vector>
using namespace std;
// Selection Sort :
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
return m;
}
}
void swap(int &a, int &b)
{
int temp = a;
a = b;
b = temp;
}
void selectionSort(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); ++i)
{
int min = findMin(arr, i);
swap(arr[i], arr[min]); // Assume a correct swap function
}
}
}
void print(vector<int> &arr)
{
if (!arr.empty())
{
for (int i = 0; i < arr.size(); i++)
{
cout << arr[i] << "";
cout << endl;
}
}
}
int main()
{
vector<int> sort;
sort.push_back(2);
sort.push_back(1);
sort.push_back(7);
sort.push_back(4);
sort.push_back(5);
sort.push_back(3);
print(sort);
cout << "this was unsorted array";
cout << endl;
cout << findMin(sort, 0);
cout << "this was minimum";
cout << endl;
selectionSort(sort);
print(sort);
}
I am getting the following results:
comparison_sort.cpp:20:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
}
^
1 warning generated.
2
1
7
4
5
3
this was unsorted array
1
this was minimum
1
2
4
5
3
0
My question is: What is causing this control path error? Why is the "7" here being replaced with a "0"?
Thanks in advance! Sorry for the noob question.
I have reviewed all my current functions and nothing seems to explain why the 7 is replaced with a 0. I have tried multiple integers and it looks like the maximum number is always replaced.
The warning is very real, and it alludes to the problem that's breaking your sort as well.
You are currently returning m inside your loop body. What that means is that if the loop is entered, then the function will return m on the very first time around the loop. It only has a chance to check the first element.
And of course, if a is the last index of the array, then the loop will never execute, and you will never explicitly return a value. This is the "control path" which does not return a value.
It's quite clear that you've accidentally put return m; in the wrong place, and even though you have good code indentation, some inexplicable force is preventing you from seeing this. To fix both the warning and the sorting issue, move return m; outside the loop:
int findMin(vector<int> &arr, int a)
{
int m = a;
for (int i = a + 1; i < arr.size(); i++)
{
if (arr[i] < arr[m])
{
m = i;
}
}
return m;
}

Recursively Generate all Combinations of given Subset Size (C++)

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(&param) {}
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;
}

How do I Reverse Display a Linked List?

I have a function that inserts random integers into a list, and a function that displays the list. With what i have now, is there a way to display that list in reverse?
void InsertRandomInts()
{
LinkedSortedList<int> list;
srand((unsigned)time(NULL));
for (int i = 0; i < 50; ++i)
{
int b = rand() % 100 + 1;
list.insertSorted(b);
}
displayListForward(&list);
}
void displayListForward(SortedListInterface<int>* listPtr)
{
cout << "The sorted list contains " << endl;
for (int pos = 1; pos <= listPtr->getLength(); pos++)
{
cout << listPtr->getEntry(pos) << " ";
}
cout << endl << endl;
}
Iterate the list from rbegin() to rend() and print it. You will be printing it in reverse.
Either 1) stop reinventing the wheel and just use a standard container that has these functions. Or 2) implement rbegin() & rend() for your custom container.
Like
for (auto it = list.rbegin(); it != it.rend(); ++it)
// Print *it
A good idea would be to get rid of that non-standard generic container and instead use std::list (or really just std::vector if you don't need list-specific semantics such as being able to remove an element without invaliding iterators to other elements).
The sort member function can be applied after all items have been added. You can then finally use rbegin and rend for reverse iteration.
Here is a simple example:
#include <iostream>
#include <list>
#include <cstdlib>
#include <ctime>
void DisplayListForward(std::list<int>& list)
{
std::cout << "The sorted list contains\n";
for (auto iter = list.rbegin(); iter != list.rend(); ++iter)
{
std::cout << *iter << " ";
}
std::cout << '\n';
}
void InsertRandomInts()
{
std::list<int> list;
std::srand(static_cast<unsigned>(std::time(nullptr)));
for (int i = 0; i < 50; ++i)
{
auto const b = std::rand() % 100 + 1;
list.push_back(b);
}
list.sort();
DisplayListForward(list);
}
int main()
{
InsertRandomInts();
}
But this may be overkill; for a quick solution, just reverse your current loop:
for (int pos = listPtr->getLength(); pos >= 1; pos--)

How do I delete a particular element in an integer array given an if condition?

I'm trying to delete all elements of an array that match a particular case.
for example..
if(ar[i]==0)
delete all elements which are 0 in the array
print out the number of elements of the remaining array after deletion
what i tried:
if (ar[i]==0)
{
x++;
}
b=N-x;
cout<<b<<endl;
this works only if i want to delete a single element every time and i can't figure out how to delete in my required case.
Im assuming that i need to traverse the array and select All instances of the element found and delete All instances of occurrences.
Instead of incrementing the 'x' variable only once for one occurence, is it possible to increment it a certain number of times for a certain number of occurrences?
edit(someone requested that i paste all of my code):
int N;
cin>>N;
int ar[N];
int i=0;
while (i<N) {
cin>>ar[i];
i++;
}//array was created and we looped through the array, inputting each element.
int a=0;
int b=N;
cout<<b; //this is for the first case (no element is deleted)
int x=0;
i=0; //now we need to subtract every other element from the array from this selected element.
while (i<N) {
if (a>ar[i]) { //we selected the smallest element.
a=ar[i];
}
i=0;
while (i<N) {
ar[i]=ar[i]-a;
i++;
//this is applied to every single element.
}
if (ar[i]==0) //in this particular case, we need to delete the ith element. fix this step.
{
x++;
}
b=N-x;
cout<<b<<endl;
i++;
}
return 0; }
the entire question is found here:
Cut-the-sticks
You could use the std::remove function.
I was going to write out an example to go with the link, but the example form the link is pretty much verbatim what I was going to post, so here's the example from the link:
// remove algorithm example
#include <iostream> // std::cout
#include <algorithm> // std::remove
int main () {
int myints[] = {10,20,30,30,20,10,10,20}; // 10 20 30 30 20 10 10 20
// bounds of range:
int* pbegin = myints; // ^
int* pend = myints+sizeof(myints)/sizeof(int); // ^ ^
pend = std::remove (pbegin, pend, 20); // 10 30 30 10 10 ? ? ?
// ^ ^
std::cout << "range contains:";
for (int* p=pbegin; p!=pend; ++p)
std::cout << ' ' << *p;
std::cout << '\n';
return 0;
}
Strictly speaking, the posted example code could be optimized to not need the pointers (especially if you're using any standard container types like a std::vector), and there's also the std::remove_if function which allows for additional parameters to be passed for more complex predicate logic.
To that however, you made mention of the Cut the sticks challenge, which I don't believe you actually need to make use of any remove functions (beyond normal container/array remove functionality). Instead, you could use something like the following code to 'cut' and 'remove' according to the conditions set in the challenge (i.e. cut X from stick, then remove if < 0 and print how many cuts made on each pass):
#include <iostream>
#include <vector>
int main () {
// this is just here to push some numbers on the vector (non-C++11)
int arr[] = {10,20,30,30,20,10,10,20}; // 8 entries
int arsz = sizeof(arr) / sizeof(int);
std::vector<int> vals;
for (int i = 0; i < arsz; ++i) { vals.push_back(arr[i]); }
std::vector<int>::iterator beg = vals.begin();
unsigned int cut_len = 2;
unsigned int cut = 0;
std::cout << cut_len << std::endl;
while (vals.size() > 0) {
cut = 0;
beg = vals.begin();
while (beg != vals.end()) {
*beg -= cut_len;
if (*beg <= 0) {
vals.erase(beg--);
++cut;
}
++beg;
}
std::cout << cut << std::endl;
}
return 0;
}
Hope that can help.
If you have no space bound try something like that,
lets array is A and number is number.
create a new array B
traverse full A and add element A[i] to B[j] only if A[i] != number
assign B to A
Now A have no number element and valid size is j.
Check this:
#define N 5
int main()
{
int ar[N] = {0,1,2,1,0};
int tar[N];
int keyEle = 0;
int newN = 0;
for(int i=0;i<N;i++){
if (ar[i] != keyEle) {
tar[newN] = ar[i];
newN++;
}
}
cout<<"Elements after deleteing key element 0: ";
for(int i=0;i<newN;i++){
ar[i] = tar[i];
cout << ar[i]<<"\t" ;
}
}
Unless there is a need to use ordinary int arrays, I'd suggest using either a std::vector or std::array, then using std::remove_if. See similar.
untested example (with c++11 lambda):
#include <algorithm>
#include <vector>
// ...
std::vector<int> arr;
// populate array somehow
arr.erase(
std::remove_if(arr.begin(), arr.end()
,[](int x){ return (x == 0); } )
, arr.end());
Solution to Cut the sticks problem:
#include <climits>
#include <iostream>
#include <vector>
using namespace std;
// Cuts the sticks by size of stick with minimum length.
void cut(vector<int> &arr) {
// Calculate length of smallest stick.
int min_length = INT_MAX;
for (size_t i = 0; i < arr.size(); i++)
{
if (min_length > arr[i])
min_length = arr[i];
}
// source_i: Index of stick in existing vector.
// target_i: Index of same stick in new vector.
size_t target_i = 0;
for (size_t source_i = 0; source_i < arr.size(); source_i++)
{
arr[source_i] -= min_length;
if (arr[source_i] > 0)
arr[target_i++] = arr[source_i];
}
// Remove superfluous elements from the vector.
arr.resize(target_i);
}
int main() {
// Read the input.
int n;
cin >> n;
vector<int> arr(n);
for (int arr_i = 0; arr_i < n; arr_i++) {
cin >> arr[arr_i];
}
// Loop until vector is non-empty.
do {
cout << arr.size() << endl;
cut(arr);
} while (!arr.empty());
return 0;
}
With a single loop:
if(condition)
{
for(loop through array)
{
if(array[i] == 0)
{
array[i] = array[i+1]; // Check if array[i+1] is not 0
print (array[i]);
}
else
{
print (array[i]);
}
}
}

How to pass vectors between multiple functions?

#include <iostream>
#include <vector>
using namespace std;
class PerformSort
{
public:
const vector<int> * p;
vector<int>& getElements(int);
vector<int>& sortArray(vector<int>&);
void printer(vector<int>&);
}firstSort;
vector<int>& PerformSort::getElements (int num)
{
vector<int> elements(num);
for (int i = 0; i < num; i++)
{
cout << "Enter elements into the array: ";
cin >> elements[i];
}
p = &elements;
return p;
}
vector<int>& PerformSort::sortArray (vector<int>& vector)
{
int holder, min;
for (int i = 0; i < (sizeof(vector) - 1); i++)
{
min = i;
for (int j = (i + 1); j < sizeof(vector); j++)
{
if (vector[j] < vector[min])
{
min = j;
}
}
if (min != i)
{
holder = vector[i];
vector[i] = vector[min];
vector[min] = holder;
}
}
return vector;
}
void PerformSort::printer(vector<int>& vector2)
{
for (int i = 0; i < sizeof(vector2); i++)
{
cout << vector2[i] << " ";
}
}
int main ()
{
int numberOfTimes;
cin >> numberOfTimes;
firstSort.printer(firstSort.sortArray(firstSort.getElements(numberOfTimes)));
return 0;
}
This returns the error: "invalid initialization of reference of type from expression of type". My first approach to create a SelectionSort algorithm was to try passing the vector by value (stupidly). After this I started to use pointers instead, after some research. However, this resulted in the aforementioned error. Declaring everything as constant does not seem to resolve the underlying error, despite how, if I understand things correctly, the error lies with temporary references being passed where constant ones are required. Any thoughts on how I might achieve this passing and returning of vectors? (I come from a Java background and am just beginning C++, so forgive me if I have made any obvious errors with regards to the pointers).
Return it by value:
vector<int> PerformSort::getElements (int num)
{
vector<int> elements(num);
for (int i = 0; i < num; i++)
{
cout << "Enter elements into the array: ";
cin >> elements[i];
}
return elements;
}
This will also let you get rid of p, which is a huge can of worms in its own right.
Finally, I notice that you use sizeof(vector) in quite a few places. This won't give you the number of elements in the vector; use vector.size() instead.
Rename the variable vector to something else:
vector<int>& PerformSort::sortArray (vector<int>& wayBetterName)
&
return wayBetterName;
What urged you to name a variable the same as a type?
There's many more other issues with the code.
You don't need pointers, you don't need the references, plus you're better off just using std::sort.