comparison of external value in count_if - c++

I want to iterate through a vector and want to get count of greater elements in another vector. I tried below code snippet, unfortunately it does not work this way.
sort(begin(vec1),end(vec1));
sort(begin(vec2),end(vec2));
for(int i = 0; i < vec1.size(); i++)
{
int val = vec1[i];
count_if(begin(vec2),end(vec2),[](int x) { return (x > val); });
}

If you want to count how many elements in vec2is greater than the i'th element in vec1 then you are doing it correct and just have to capture val in the lambda
for(int i = 0; i < vec1.size(); i++)
{
int val = vec1[i];
auto res = count_if(begin(vec2),end(vec2), [val](int x) { return (x > val); });
}
but if you want to compare each element in vec2 with the corresponding element in vec1 you have to do it manually.
int count = 0;
//here the sizes of vec1 and vec2 must be equal
for (auto it1 = begin(vec1), it2 = begin(vec2); it1 != end(vec1); ++it1, ++it2) {
if (*it2 > *it1)
++count;
}
EDIT:
As #Jarod42 commented. It is possible to use an algorithm for the second case
auto res = std::transform_reduce(begin(vec2), end(vec2), begin(vec1), 0,
std::plus<>(), std::greater<>());

Related

How to convert a string of HashSet to a 2D vector in c++ ? This is a 3-sum problem in leetcode

// nums = [-1,0,1,2,-1,-4]
// result should be = {{-1,-1,2},{-1,0,1}}
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
unordered_set<string> s;
for(int start1=0; start1<nums.size(); start1++){
for(int start2=start1+1; start2<nums.size(); start2++){
for(int start3=start2+1; start3<nums.size(); start3++){
string str = "";
if(nums[start1]+nums[start2]+nums[start3] == 0){
str += to_string(nums[start1])+
to_string(nums[start2])+
to_string(nums[start3]);
}
s.insert(str); //s{"-1-12","-101"}
}
}
}
After inserting values to set s, s look as follows
s{"-1-12","-101"}
The problem is how I can convert that set to a 2d vector in c++.
I wanted to return a 2D vector of integers.
You want to return a 2D vector of integers and declare the function to return vector<vector<int>>, which is fine - but you never return anything from the function.
Instead of populating a vector<int> in your inner loop, you've chosen to populate a string. That must be changed.
Using an unordered_set<vector<int>> will however not work "out of the box" because there is no standard hashing function for vector<int>. I suggest using a set instead which only requires operator< to be defined, which it is for vector<int>.
"result should be = {{-1,-1,2},{-1,0,1}}" - but that's not what your algorithm produces. It produces {{},{-1,-1,2},{-1,0,1}} since it'll insert elements even when nums[start1]+nums[start2]+nums[start3] != 0.
Example with suggested fixes:
std::vector<std::vector<int>> threeSum(std::vector<int>& nums) {
std::sort(nums.begin(), nums.end());
std::set<std::vector<int>> s; // using a set<vector<int>> instead
for (size_t start1 = 0; start1 < nums.size(); start1++) {
for (size_t start2 = start1 + 1; start2 < nums.size(); start2++) {
for (size_t start3 = start2 + 1; start3 < nums.size(); start3++) {
if (nums[start1] + nums[start2] + nums[start3] == 0) {
// only insert when a match is found to produce the
// expected result
s.insert({nums[start1], nums[start2], nums[start3]});
}
}
}
}
// populate the std::vector<std::vector<int>> by using the begin() and
// end() iterators of `s`:
return {s.begin(), s.end()};
}
Demo
Since copying the inner vector<int>s may be an expensive operation, you can, since C++17, also move them from the set<vector<int>> into the vector<vector<int>>.
std::vector<std::vector<int>> threeSum(std::vector<int>& nums) {
std::sort(nums.begin(), nums.end());
std::set<std::vector<int>> s;
for (size_t start1 = 0; start1 < nums.size(); start1++) {
for (size_t start2 = start1 + 1; start2 < nums.size(); start2++) {
for (size_t start3 = start2 + 1; start3 < nums.size(); start3++) {
if (nums[start1] + nums[start2] + nums[start3] == 0) {
s.insert({nums[start1], nums[start2], nums[start3]});
}
}
}
}
std::vector<std::vector<int>> rv;
for(std::set<std::vector<int>>::iterator it = s.begin(), next;
it != s.end(); it = next)
{
next = std::next(it);
// extract and move:
rv.push_back(std::move(s.extract(it).value()));
}
return rv;
}
Demo

erase rows and colums of a 2D vector, when a condition is achieved in another single vector?

I have a matrix (vector of vector), in other words, 2D vector (6 X 6) elements <double>, and after I have a vector with 6 elements <int>. the vector with ints has only "0" and "1". Then, I am looking for a way to remove a row and column of the 2D vector when a "0" is found in the vector (1D) of ints. This time is only 6 X 6 but later on, will be around 100 X 100.
What I've done is use iterators, and I successfully remove the rows but now I don't know how to tackle the columns.
This is my code.
#include <iostream>
#include <vector>
#include <iomanip>
int main() {
std::vector <int> boundaryConditions = { 0,1,1,1,0,0 };
std::vector <std::vector<double>> matrix = { {1.46371e+07, 1.46371e+07, -1.46371e+07, -1.46371e+07, 0, 0},
{1.46371e+07, 5.60371e+07, -1.46371e+07, -1.46371e+07, 0, -4.14e+07},
{-1.46371e+07, -1.46371e+07, 5.60371e+07, 1.46371e+07, -4.14e+07, 0},
{-1.46371e+07, -1.46371e+07, 1.46371e+07, 1.46371e+07, 0, 0},
{0, 0, -4.14e+07, 0, 4.14e+07, 0},
{0, -4.14e+07, 0, 0, 0, 4.14e+07}};
int i = 0;
std::vector<int>::iterator it = boundaryConditions.begin();
while (it != boundaryConditions.end())
{
if (*it == 0)
{
it = boundaryConditions.erase(it);
matrix.erase(matrix.begin() + i);
}
else
{
it++;
i++;
}
}
for (int i = 0; i < matrix.size(); i++)
{
for (int j = 0; j < matrix[i].size(); j++)
{
std::cout << matrix[i][j] << std::setw(15);
}
std::cout << "\n";
}
system("pause>0");
}
You can create a new matrix after you've removed the rows.
std::vector<std::vector<double>> removeColumns(const std::vector<int>& boundaryConditions,
const std::vector<std::vector<double>>& matrix)
{
std::vector<std::vector<double>> returnValue(matrix.size());
size_t curRow = 0;
size_t curCol = 0;
for (auto& v : returnValue)
{
for (size_t curCol = 0; curCol < matrix[0].size(); ++curCol)
{
if (boundaryConditions[curCol] == 1)
v.push_back(matrix[curRow][curCol]);
}
++curRow;
}
return returnValue;
}
Then you would call it like this, given that you have already removed the rows from matrix:
matrix = removeColumns({0,1,1,1,0,0}, matrix);
Here is a Live Example.
If you want an in-place solution, here is an example:
void removeColumns(const std::vector<int>& boundaryConditions, std::vector<std::vector<double>>& matrix)
{
size_t curCol = 0;
for (size_t i = 0; i < boundaryConditions.size(); ++i)
{
if (boundaryConditions[i] == 0)
{
for (auto& v : matrix)
v.erase(v.begin() + curCol);
}
else
++curCol;
}
}
Then it would be called like this:
removeColumns({0,1,1,1,0,0}, matrix);
Here is a Live Example
Another solution, if feasible for you, is to mark each entry to erase with a value, maybe std::numeric_limits<double>::max(). Then in a second pass, use erase/remove idiom, thus reducing the number of erase calls needed.
Here is an example:
void removeColumns(const std::vector<int>& boundaryConditions,
std::vector<std::vector<double>>& matrix)
{
// Mark the entries to delete
for (size_t i = 0; i < boundaryConditions.size(); ++i)
{
if (boundaryConditions[i] == 0)
std::for_each(matrix.begin(), matrix.end(),[&](std::vector<double>& vect)
{ vect[i] = std::numeric_limits<double>::max(); });
}
// One pass through the matrix to remove the marked entries.
for (auto& v : matrix)
v.erase(std::remove(v.begin(), v.end(), std::numeric_limits<double>::max()), v.end());
}
Here is a Live Example
Note that std::remove doesn't really remove anything, thus doesn't incur the penalty of an actual erase.
The single erase call erases an entire range, not just single values, thus has the potential to be faster than the first in-place solution given (but you have to time them, I can't guarantee which is faster).
Maybe this could help, not fully tested:
Let A be the binaryConditions array,
void reduce(std::vector<int> A, std::vector<int> &target) {
int i = 0, j = 0;
int nOnes = 0;
while (i<A.size() && j < A.size()) {
if (A[i] != 0) {
++i;
nOnes++;
}
else {
j = max(i + 1, j);
while (j < A.size() && A[j] == 0) ++j;
if (j >= A.size()) break;
swap(A[i], A[j]);
swap(target[i], target[j]);
}
}
A.resize(nOnes);
target.resize(nOnes);
}

Searching in vectors of pairs

I have a 2d vector of pairs and I would like get in which row is a given pair.
I tried to iterate through all the elements but I didn't succeed.
Here is the adjacency matrix of an undirected, weighted graph:
vector<pair<int,int >> adj[20];
for (int i = 1; i <= nodes; i++){
f >> x >> y >> weight;
adj[x].push_back(make_pair(weight, y));
adj[y].push_back(make_pair(weight, x));
}
And it looks like something like this:
(4,2),(5,3)
(4,1),(6,3)
(5,1),(6,2)
I am trying to find in which row is the pair (6,2)
typedef pair<int, int>p;
p pair= make_pair(6, 2);
cout << which_row(adj, pair);
Here is what I tried first:
int which_row(vector<p>adj[20], p pair) {
vector <pair<int, int>> ::iterator it;
for (int i = 0; i < adj->size(); i++) {
for (int j = 0; j < adj[i].size(); i++)
if (pair.first == adj[i][j].first && pair.second == adj[i][j].second)
return i;
}
return -1;
}
but it does not step in the for loop.
Second:
int which_row(vector<p>adj[20], p pair) {
vector <pair<int, int>> ::iterator it;
for (int i = 0; i <= adj->size(); i++) {
for (it = adj[i].begin(); it != adj[i].end(); it++)
if (pair.first == it->first && pair.second == it->second)
return i;
}
}
But it does not step in the second for loop.
What can I do?
Since we can infer your x and y inputs from the pairs you gave us, you never push anything into adj[0]. adj->size() is the same as adj[0].size(). You never pushed anything into this so it will be 0. It seems you want to go over every row? Each row contains a vector? Each vector contains some pairs? Make adj a vector<vector<pair<int, int>>> so you can access adj.size(). That's likely what you want. Or iterate from i = 0; i < 20; i++ to go over each row.
Change your iteration to:
int which_row(vector<p>adj[20], p pair) {
for (int i = 0; i < 20; i++) { // <-- changed to < 20 (not <= 20)
for (auto it = adj[i].begin(); it != adj[i].end(); it++)
if (pair == *it) // <-- pairs compare as you'd expect, no need to compare each element
return i;
}
return -1; // need to return something if not found
}
Or we can take advantage of std::find in the <algorithm> library:
#include <algorithm>
int which_row(vector<p>adj[20], p pair) {
for (int i = 0; i < 20; i++) { // <-- changed to < 20 (not <= 20)
if (std::find(adj[i].begin(), adj[i].end(), pair) != adj[i].end())
return i;
}
return -1; // need to return something if not found
}
If you change your adj initialization to std::vector<std::vector<p>> adj(20); you can change your which_row to:
// in main or whatever:
// makes a vector of 20 default-initialized (empty) vector<p>
std::vector<std::vector<p>> adj(20);
// elsewhere:
int which_row(vector<vector<p>> adj, p pair) {
for (auto i = 0; i < adj.size(); i++) { // <-- adj is a vector now
if (std::find(adj[i].begin(), adj[i].end(), pair) != adj[i].end())
return i;
}
}
return -1; // need to return something if not found
}

all combinations of k elements out of n

Can somebody provide me a link or pseudocode of a function for finding all combinations of k elements out of n? possibly in STL. I don't need to compute n choose k, I need to list all vectors of numbers of size k.
Thanks
In C++ given the following routine:
template <typename Iterator>
inline bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
/* Credits: Thomas Draper */
if ((first == last) || (first == k) || (last == k))
return false;
Iterator itr1 = first;
Iterator itr2 = last;
++itr1;
if (last == itr1)
return false;
itr1 = last;
--itr1;
itr1 = k;
--itr2;
while (first != itr1)
{
if (*--itr1 < *itr2)
{
Iterator j = k;
while (!(*itr1 < *j)) ++j;
std::iter_swap(itr1,j);
++itr1;
++j;
itr2 = k;
std::rotate(itr1,j,last);
while (last != j)
{
++j;
++itr2;
}
std::rotate(k,itr2,last);
return true;
}
}
std::rotate(first,k,last);
return false;
}
You can then proceed to do the following:
// 9-choose-3
std::string s = "123456789";
std::size_t k = 3;
do
{
std::cout << std::string(s.begin(),s.begin() + k) << std::endl;
}
while(next_combination(s.begin(),s.begin() + k,s.end()));
Or for a std::vector of int's:
// 5-choose-3
std::size_t n = 5;
std::size_t k = 3;
std::vector<int> ints;
for (int i = 0; i < n; ints.push_back(i++));
do
{
for (int i = 0; i < k; ++i)
{
std::cout << ints[i];
}
std::cout << "\n";
}
while(next_combination(ints.begin(),ints.begin() + k,ints.end()));
http://howardhinnant.github.io/combinations.html
Search for "for_each_combination". If you find something faster, please let me know. Unlike other algorithms I often see, this one doesn't require the element type to be LessThanComparable.
Create an auxiliary vector with n - k zeros followed by k ones. A zero means the element in the original container is not included, whereas one means the element is included.
Now use std::next_permutation on the auxiliary vector to get the next combination.
Here is a lazy example of pseudocode that can get the job done...
void nChooseK(array[n],k){
recurse("",array[n],k);
}
void recurse(initialString,array[n],k){
if(k == 0){
print initialString;
return;
}
for(i=0;i<n;i++){
tmpArray = array[0...i-1]+array[i+1...];//the array without the object to remove
recurse(initialString + array[i], tmpArray,k-1)
}
}
You could use std::next_permutation but it is n! and not n choose k. You could filter them after you created them. But this solution is O(n!), not really perfect. Here is the trial and error solution:
int factorial(int value)
{
int result = 1;
for(int i = 1; i <= value; i++)
{
result *= i;
}
return result;
}
std::set<std::set<int>> binomial_coefficient(std::vector<int> input, int k)
{
std::set<std::set<int>> solutions;
for(unsigned int i = 0; i < factorial(input.size()); i++)
{
std::next_permutation(input.begin(), input.end());
solutions.insert(std::set<int>(input.begin(), input.begin() + k));
}
return solutions;
}

How to compare and remove elements that does not have same value between 3 vectors?

I need to remove every elements that doesn't have same value between 3 vectors or more.
For example,
vector<int> Vector1, Vector2, Vector3;
for(int i = 2; i < 7; i++) Vector1.push_back(i); // Vector1 = {2, 3, 4, (5), (6)}
for(int i = 3; i < 8; i++) Vector2.push_back(i); // Vector2 = {3, 4, (5), (6), 7}
for(int i = 5; i < 10; i++) Vector3.push_back(i); // Vector3 = {(5), (6), 7, 8, 9}
We know that all of the vectors has 2 elements with same value: 5 and 6. Now how do I get these values and store them to a new vector?
Any kind of help would be appreciated :)
You have set_intersection in the standard algorithms library(vectors must be sorted):
// This code does it for two vectors only
vector<int> a, b, r;
for(int i = 0; i < 10; i++)
{
a.push_back(i);
b.push_back(i+5);
}
set_intersection(
a.begin(), a.end(),
b.begin(), b.end(),
back_inserter(r));
If all the vectors are ordered then you just scan them each time checking the lowest number until you pass it on one of the other two. if you can't find it, you drop it, each time you check the lowest number you get.
Example:
T1 = first element (v1)
T2 = firest elemnt (v2)
T3 = first element (v3)
find out the loweset one between the 3
if there is no equals - drop it and get the next val, and try again.
if all the vectors has the numbers going up (ordered) you'll find all matches.
For me the fastest solution is to build the set with elements from all vectors. Every time you inserts element that is not unique you increment his counter. Elements with counter equal numbers of vectors should be deleted.
However the simplest implementation is to make map (for most cases I think it is fast enough):
// only pseudo code
map<int,int> elems;
for( vector<int>& v : vectors )
for( int i : v ) {
map<int,int>::iterator itr = elems.find(i);
if( itr == elems.end() )
elems[i] = 1;
else itr->second++;
}
for( pair<int,int>& p : elems )
if( p.second == vectors.size() )
erase_from_vectors( p.first );
If your vectors are really huge you may build multimap that in value contains vector::iterators. Then you can remove those elements from vectors without looking through them.
If the vectors are not ordered and it is not possible to sort them, you can use this (in-efficient) approach:
#include <iostream>
#include <vector>
#include <algorithm>
typedef std::vector<int> IntVec;
typedef std::vector<IntVec> TwoDIntVec;
IntVec
intvec_union(const TwoDIntVec& vec)
{
IntVec result;
size_t vec_size = vec.size();
if (vec_size < 3) return result;
const IntVec& vec1 = vec[0];
size_t sz = vec1.size();
for (size_t i=0; i<sz; ++i)
{
bool found = true;
int val = vec1[i];
for (size_t j=1; j<vec_size; ++j)
{
const IntVec& v = vec[j];
if (std::find(v.begin(), v.end(), val) == v.end())
{
found = false;
break;
}
}
if (found) result.push_back(val);
}
return result;
}
// test
int
main()
{
IntVec Vector1, Vector2, Vector3;
for(int i = 2; i < 7; i++) Vector1.push_back(i); // Vector1 = {2, 3, 4, (5), (6)}
for(int i = 3; i < 8; i++) Vector2.push_back(i); // Vector2 = {3, 4, (5), (6), 7}
for(int i = 5; i < 10; i++) Vector3.push_back(i); // Vector3 = {(5), (6), 7, 8, 9}
TwoDIntVec v;
v.push_back(Vector1);
v.push_back(Vector2);
v.push_back(Vector3);
IntVec result = intvec_union(v); // result = {5,6}
return 0;
}
This seems to work, although it looks ugly:
void intersection(std::vector<std::vector<int>*> valList, std::vector<int>& intersectionList)
{
if(valList.size() < 2)
{
return;
}
std::vector<std::vector<int>*>::iterator iter = valList.begin();
std::vector<std::vector<int>*>::iterator endIter = valList.end();
for(; iter != endIter; ++iter)
{
std::vector<int>* pVec = *iter;
std::sort(pVec->begin(), pVec->end());
}
iter = valList.begin();
endIter = valList.end();
std::vector<int>* pFirstVec = *iter;
std::vector<int>* pSecondVec = *(iter + 1);
iter = iter + 2;
std::set_intersection(pFirstVec->begin(), pFirstVec->end(), pSecondVec->begin(), pSecondVec->end(), std::back_inserter(intersectionList));
for(; iter != endIter; ++iter)
{
std::vector<int> temp;
std::vector<int>* pVec = *iter;
std::set_intersection(pVec->begin(), pVec->end(), intersectionList.begin(), intersectionList.end(), std::back_inserter(temp));
intersectionList = temp;
std::sort(intersectionList.begin(), intersectionList.end());
}
}
int main()
{
std::vector<int> Vector1, Vector2, Vector3, Vector4;
for(int i = 2; i < 7; i++) Vector1.push_back(i); // Vector1 = {2, 3, 4, (5), (6)}
for(int i = 3; i < 8; i++) Vector2.push_back(i); // Vector2 = {3, 4, (5), (6), 7}
for(int i = 5; i < 10; i++) Vector3.push_back(i); // Vector3 = {(5), (6), 7, 8, 9}
for(int i = 6; i < 12; i++) Vector4.push_back(i); // Vector3 = {(6),7,8,9,10,11}
std::vector<int> r;
std::vector<std::vector<int>*> v;
v.push_back(&Vector1);
v.push_back(&Vector2);
v.push_back(&Vector3);
v.push_back(&Vector4);
intersection(v,r);
return 0;
}
Other answers seems to assume that the vectors are sorted or don't have repeated values (I think gba's answer fails in that case).
This one works in every cases and still try to be efficient. It removes all elements found in every vectors.
template <class C>
struct is_in{
const C & c_;
bool b_;
is_in(C c, bool b = true) : c_(c), b_(b) {}
bool operator() (typename C::value_type v){
return b_ == (c_.find(v) != c_.end());
}
};
int main() {
set<int> s(v.front().begin(), v.front().end());
typedef is_in<set<int> > is_in_set;
vector< vector<int> >::iterator i;
for(i = v.begin()+1; i != v.end(); ++i) {
//s is the intersection of every vectors before i
set<int> new_s;
//copy in new_s all elements of *i unless they are not in s
remove_copy_if(i->begin(), i->end(), insert_iterator<set<int> >(new_s, new_s.begin()),
is_in_set(s, false));
swap(s, new_s);
}
for(i = v.begin(); i != v.end(); ++i) {
//erase all elements of *i which are in s
i->erase(remove_if(i->begin(), i->end(),
is_in_set(s)), i->end());
}
vector<int> res_vec(s.begin(), s.end());
}
This approach relies on having sorted input vectors, but after that will only do an linear walk through the current and next vectors to be compared, keeping the matching elements in the first vector. It doesn need to do a full search for each element. The algorithm is reasonably container neutral, requiring only forward iterators so will work with vectors, lists, singly linked lists, raw arrays, etc.
The essential building block for this algorithm is a function that removes elements from a sorted range that aren't in a second sorted range. I'm using the std::remove convention of swapping unwanted elements to the end of the range and returning an iterator pointing to start of the unwanted elements. It's O(n + m).
template<class Input1, class Input2>
Input1 inplace_intersection(Input1 first1, Input1 last1, Input2 first2, Input2 last2)
{
using std::swap;
Input1 nextslot(first1);
for( ; first1 != last1; ++first1 )
{
// Skip elements from the second range that are
// smaller than the current element.
while( first2 != last2 && *first2 < *first1 )
++first2;
// Do we have a match? If so keep
if( first2 != last2 && !(*first1 < *first2) )
{
if( first1 != nextslot )
swap( *first1, *nextslot );
++nextslot;
}
}
return nextslot;
}
With this building block you can operate on sorted vectors this.
std::vector<int> initial;
// fill...
std::vector<int>::iterator first = initial.begin(), last = initial.end();
last = inplace_intersection( first, last, scnd.begin(), scnd.end() );
last = inplace_intersection( first, last, thrd.begin(), thrd.end() );
// etc...
initial.erase( last, erase.end() );
If your input vectors aren't sorted, then you can sort them in place if possible, or otherwise create sorted copies.