Passing 2-D vector to class - c++

This is my attempt at passing a N-D vector of arbitrary element types, inner and outer lengths to a class and printing its contents.
I know there are a few issues but I have not been able to resolve.
How would I assign the arbitrary inner vector length to a variable or set of variables?
I have attempted to pass iterators to the constructor and assign them to member variables (with and without passing the vector) but that has not been successful.
I understand there are libraries for handling matrix objects and other questions which address problems similar to the one posed herein, however, there are unique/fringe scenarios which comprise the motivation for this question.
#include <iostream>
#include <iterator>
#include <vector>
template <typename V, typename I>
class myVec{
private:
I rows;
I cols;
std::vector< std::vector<V> > vec( rows , vector<int> (cols));
public:
myVec(std::vector< std::vector<V> > const &myArr){
vec = myArr;
rows = myArr.size();
cols = myArr[].size();
}
void printVec(){
for(int i = 0; i < vec.size(); i++){
std::cout << "{";
for(int j = 0; j < vec[i].size(); j++){
std::cout << vec[i][j];
}
if (i < vec.size()){
std::cout << "}";
if (i < vec.size()-1){
std::cout << ",";
std::cout << " ";
}
}
}
std::cout << std::endl;
}
};
int main () {
std::vector< std::vector<int> > mainVec = {{1, 2, 4}, {5, 6, 7, 8}, {4, 3, 2, 1, 7}, {8, 7, 6, 5, 9, 3}};
myVec<int, int> vec1 = myVec<int, int>(mainVec);
vec1.printVec();
return 0;

Basic solution that utilizes iterators as previously suggested for the print method. The vector is passed by const ref, how much of an advantage is there to using move assign instead? Index operator overloads and access methods are not included at this time, plan to include exception handling for out of bounds and other cases.
#include <iostream>
#include <vector>
template <typename V>
class myVec{
private:
std::vector< std::vector<V> > vec;
public:
myVec();
explicit myVec(const std::vector< std::vector<V> > &myArr):vec(myArr) {};
explicit myVec(std::vector< std::vector<V> > &&myArr):vec(std::move(myArr)) {};
}
void printVec(){
std::cout << '{';
for(auto& row:vec){
if(&row != &vec.front()) std::cout << ", ";
std::cout << '{';
if(auto cln = row.begin(); cln != row.end()) {
std::cout << *cln;
for(++cln; cln != row.end(); ++cln) std::cout << ", " << *cln;
}
std::cout << '}';
}
std::cout << '}' << std::endl;
}
};
int main () {
std::vector< std::vector<int> > mainVec = {{1, 2, 4}, {5, 6, 7, 8}, {4, 3, 2, 1, 7}, {8, 7, 6, 5, 9, 3}};
myVec<int, int> vec1 = myVec<int, int>(mainVec);
vec1.printVec();
return 0;

Related

Is there an algorithm that checks whether a container contains only distinct elements?

Hello I want to find some algorithm that checks whether a container contains all distinct elements.
Here is what I've tried:
template <typename It>
bool hasAllDistinctElems(It first, It last){
for(auto i = first; i != last; ++i)
for(auto j = i; ++j != last; )
if(*i == *j )
return false;
return true;
}
int main(){
std::vector<int> vi{5, 7, 3, 8, 2, 7, 5};
std::deque<int> di{1, 5, 7, 2, 3, 8, 6};
std::cout << hasAllDistinctElems( vi.cbegin(), vi.cend() ) << '\n'; // 0
std::cout << hasAllDistinctElems( di.cbegin(), di.cend() ) << '\n'; // 1
}
It works just fine but I've found another method:
copy all the elements of the first container into a container that guarantees the uniqueness of its elements like the STL associative containers like std::set, std::map.
Compare the sizes of the containers so if the sizes are equal it means all the elements from the first one has been copied to the set which means they are all unique otherwise they are not unique thus not all of them have been copied into the set:
#include <unordered_set>
#include <deque>
#include <vector>
#include <iostream>
int main(){
std::vector<int> vi{5, 7, 3, 8, 2, 7, 5};
std::deque<int> di{1, 5, 7, 2, 3, 8, 6};
std::unordered_set<int> usi(vi.cbegin(), vi.cend());
std::unordered_set<int> usi2(di.cbegin(), di.cend());
std::cout << std::boolalpha;
std::cout << "vi's all distinct? " << (vi.size() == usi.size()) << '\n'; // false
std::cout << "di's all distinct? " << (di.size() == usi2.size()) << '\n'; // true
}
Both work fine but I'd like to know which one should I use? Is there an algorithm that does that?? or another workaround? Thank you!

How to replace the 2D vector corresponding to the values?

I am trying to replace the elements in a 2D vector (vector<vector<int>>). I want to change the elements not only by one value, but by a list, which means, for example, change 1,3,4,5,8,9 to 1,2,3,4,5,6 one-to-one correspondence. I have made a very slow code with double loops. Is there any way to speed up the process, with new function or sort the element? Because my 2D vector is very big, 3*300000 actually. My example code is below:
int myints[] = { 1,3,4,5,8,9 };
int myints2[] = { 1,2,3,4,5,6 };
std::vector<int> vals (myints, myints+6);
std::vector<int> vals2 (myints2, myints2+6);
vector<vector<int>> V0(3);
V0[0]={1,4,5};
V0[1]={3,1,8};
V0[2]={1,9,4};
for (size_t j = 0; j < V0.size(); j++)
{
for (int i = 0; i < vals.size(); i++)
replace(V0[j].begin(), V0[j].end(), vals[i], vals2[i]);
};
The ideal output V0 should be
1 3 4
2 1 5
1 6 3
You can use an unordered_map to replace each value directly, instead of searching through the whole vector for each replacement:
#include <vector>
#include <unordered_map>
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
unordered_map<int, int> replacements{{1, 1}, {3, 2}, {4, 3}, {5, 4}, {8, 5}, {9, 6}};
vector<vector<int>> v0(3);
v0[0] = {1, 4, 5};
v0[1] = {3, 1, 8};
v0[2] = {1, 9, 4};
for_each(v0.begin(), v0.end(), [&](vector<int>& v)
{
transform(v.begin(), v.end(), v.begin(), [&](int val)
{
auto it = replacements.find(val);
return it != replacements.end() ? replacements[val] : val;
});
});
// Print
for (auto& v : v0)
{
cout << "[ ";
for (auto val : v)
{
cout << val << ", ";
}
cout << "]" << endl;
}
return 0;
}
Output:
[ 1, 3, 4, ]
[ 2, 1, 5, ]
[ 1, 6, 3, ]
In C++17, you may also choose a parallel execution policy in for_each and/or transform, since all the changes can be done in parallel.

Sort one vector using another in nonincreasing order

This mean that while I am sorting the v2 in the nonincreasing order, the v1 should looks like this:
Vectors look as following.
v1 = {0, 5, 5, 2, 10};
v2 = {0 ,2, 6, 20, 5};
The output:
v1 = {2, 5, 10, 5, 0};
v2 = {20, 6, 5, 2, 0};
I was trying to solve that problem mixing std::sort and lambdas.
That is why I have read several questions about std::sort, there were no answers which solve the problem similar to mine so that is why I am asking.
I am especially interested in the answers which contains it's usage or other features of C++11 and C++14.
It is not a question like:
"I completely do not know what to do."
I know how to achieve the output using C++98, but I am wondering if there is an more efficient and prettier way to do it.
Big thanks for your help :)
You could zip, sort, and unzip.
#include <iostream>
#include <vector>
#include <algorithm>
//converts two vectors into vector of pairs
template <typename T, typename U>
auto zip(T t, U u) {
std::vector<std::pair<typename T::value_type,typename U::value_type>> pairs;
for (size_t i = 0; i < t.size(); ++i){
pairs.emplace_back(u[i],t[i]);
}
return pairs;
}
//converts a vector of pairs, back into two two vectors
template <typename T, typename U, typename V>
void unzip(V pairs, T & t, U & u) {
for (auto const& it: pairs){
u.emplace_back(it.first);
t.emplace_back(it.second);
}
}
int main(){
//vectors
std::vector<int> v1 = {0, 5, 5, 2, 10};
std::vector<int> v2 = {0 ,2, 6, 20, 5};
//zip vectors
auto pairs = zip(v1,v2);
//sort them
std::sort(pairs.begin(),pairs.end(),std::greater<>());
//unzip them
v1.clear();
v2.clear();
unzip(pairs,v1,v2);
//print
std::cout << '\n';
for (auto i: v1) std::cout << i << ' ';
std::cout << '\n';
for (auto i: v2) std::cout << i << ' ';
std::cout << '\n';
}
Well, I don't if this is would be efficient, or not, but this demonstrates how to do this with std::generate, std::sort, and std::transform, with some extra seasoning from mutable lambdas, and iterators.
#include <algorithm>
#include <iostream>
int main()
{
std::vector<int> v1={0, 5, 5, 2, 10},
v2 = {0, 2, 6, 20, 5};
std::vector<int> index;
index.resize(5);
std::generate(index.begin(), index.end(),
[n=0]
()
mutable
{
return n++;
});
std::sort(index.begin(), index.end(),
[&]
(auto &a, auto &b)
{
return v2[b] < v2[a];
});
std::vector<int> v1_out, v2_out;
std::transform(index.begin(), index.end(),
std::back_insert_iterator<std::vector<int>>(v1_out),
[&]
(auto a)
{
return v1[a];
});
std::transform(index.begin(), index.end(),
std::back_insert_iterator<std::vector<int>>(v2_out),
[&]
(auto a)
{
return v2[a];
});
for (auto n: v1_out)
std::cout << n << ' ';
std::cout << std::endl;
for (auto n: v2_out)
std::cout << n << ' ';
std::cout << std::endl;
}
Big thanks for all your answers. I found an easy way to achieve the same effect and the idea comes from this answer.
1.
Firstly I used all code from answer which I linked, so it is:
template <typename T>
vector<size_t> sort_indexes(const vector<T> &v)
{
// initialize original index locations
vector<size_t> idx(v.size());
for (size_t i = 0; i != idx.size(); ++i) idx[i] = i;
// sort indexes based on comparing values in v
sort(idx.begin(), idx.end(),
[&v](size_t i1, size_t i2)
{
return v[i1] >= v[i2];
});
return idx;
}
2.Then I did a function which will sort first and a second vector using the third one.To achieve it I had to create temporary vectors one for a first vector, one for a second, and two for the last one.
Why two?
Because I have to remember the sorted indexes of the third vector and I need a one temporary to which I will be pushing elements of the original third vector according to sorted indexes.
void SortByIndexes(vector<int>& Pi,vector<int> &Wi,vector<int>& PidivWi)
{
vector<int> Pitemp, Witemp, PidivWitemp,SortedIndexes;
for (auto i : sort_indexes(PidivWi))
{
SortedIndexes.push_back(i);
}
for (auto i : SortedIndexes)
{
Pitemp.push_back(Pi[i]);
Witemp.push_back(Wi[i]);
PidivWitemp.push_back(PidivWi[i]);
}
swap(Pi, Pitemp);
swap(Wi, Witemp);
swap(PidivWi,PidivWitemp);
}
3. After sorting just swap sorted vectors with original ones.
Done.
Thank you all guys.

Kick out duplicate entries across vectors

I have vectors and I would like to retrieve one vector that contains all entries which aren't duplicated anywhere in all input vectors.
#include <vector>
int main() {
std::vector<int> a = {2, 1, 3};
std::vector<int> b = {99, 1, 3, 5, 4};
std::vector<int> c = {5, 6, 7, 1};
// magic to retrieve {2, 99, 4, 6, 7} (order doesn't matter)
}
Is there a library function that can help performing this task efficiently?
I'm not tied to using vectors. The solution could include lists, sets, or whatever are most appropriate for the task.
Using unordered_map, O(N) space complexity and O(N) time complexity:
#include <vector>
#include <unordered_map>
#include <iostream>
std::vector<int>
get_unique_values(std::initializer_list<std::vector<int>> vectors)
{
std::unordered_map<int, size_t> tmp;
auto insert_value_in_tmp = [&tmp](int v) {
auto i = tmp.find(v);
if (i == tmp.end())
tmp[v] = 1;
else if (i->second != 2)
i->second = 2;
};
for ( auto& vec : vectors) {
for ( auto vec_value : vec ) {
insert_value_in_tmp(vec_value);
}
}
std::vector<int> result;
for (auto v : tmp) {
if (v.second == 1)
result.push_back(v.first);
}
return result;
};
int main() {
std::vector<int> a = {2, 1, 3};
std::vector<int> b = {99, 3, 5, 4};
std::vector<int> c = {5, 6, 7};
std::vector<int> result = get_unique_values({a,b,c});
for (auto v : result) {
std::cout << v << " ";
}
std::cout << '\n';
return 0;
}

Efficiently sort subset of the vector that defines the order

I have the vector that defines the order of items (0..N-1), e.g.
{5, 0, 4, 3, 2, 1, 7, 6}.
I have to sort subsets of that vector. So, for {0, 1, 2, 5} I should get {5, 0, 2, 1}.
I tested the following solutions:
Create a set of items in a subset, then clear the subset, go through the ordering vector, adding only items in the set.
Create new sorted vector by going through the ordering vector, adding only items found by in the subset by std::lower_bound.
The second solution seems much faster, although it needs subset to be sorted. Are there any better solutions? I am using C++/STL/Qt, but the problem is probably not language-dependent.
Check this code :-
#include <iostream>
#include <algorithm>
#include <vector>
struct cmp_subset
{
std::vector<int> vorder;
cmp_subset(const std::vector<int>& order)
{
vorder.resize(order.size());
for (int i=0; i<order.size(); ++i)
vorder.at(order[i]) = i;
}
bool operator()(int lhs, int rhs) const
{
return vorder[lhs] < vorder[rhs];
}
};
int main()
{
std::vector<int> order = {5, 0, 4, 3, 2, 1, 7, 6};
std::vector<int> subset = {0, 1, 2, 5};
for (auto x : subset)
std::cout << x << ' ';
std::cout << '\n';
std::sort(subset.begin(), subset.end(), cmp_subset(order));
for (auto x : subset)
std::cout << x << ' ';
std::cout << '\n';
return 0;
}
The code is copied from here