I want to be able to accumulate every other pair of elements in a vector using accumulate. I tried the following without much success, returning an error for a non-empty, non-zero vector
return std::accumulate(vec.begin(), vec.end(), 0,
[&](int runningSum, int first, int second)
{return runningSum = runningSum + min(first, second);});
which I now realise probably wouldn't be getting the minimum between pairs. For instance, if I have
vector<int> vec = {1,4,2,3}
I want to return 0 + min(1, 4) + min(2, 3).
On another note, is there any website with many examples of these STL built-ins? I find the examples online far and few. I really want to see the power of accumulate, and get comfortable with it.
std::accumulate() does not allow you to use a predicate with 3 parameters, only 2 parameters - the current running sum, and the current element to be added to that sum. The predicate is called for each individual element and is expected to return the updated sum.
If you want to sum the values in pairs, you can try something like this instead:
vector<int> vec = {1,4,2,3};
...
int *first = nullptr;
return std::accumulate(vec.begin(), vec.end(), 0,
[&](int runningSum, int &value) {
if (first) {
runningSum += std::min(*first, value);
first = nullptr;
} else {
first = &value;
}
return runningSum;
}
);
A better solution would be to simply change your vector to hold a pair of ints (like std::pair<int, int>) as its element type (or at least copy your vector ints to a second vector of pairs), and then you can accumulate the pairs as-is:
vector<pair<int,int>> vec = {{1,4},{2,3}};
...
return std::accumulate(vec.begin(), vec.end(), 0,
[](int runningSum, const pair<int, int> &p) {
return runningSum + std::min(p.first, p.second);
}
);
I think it would be difficult to just use accumulate straight away to sum by min of pairs. You would need to maybe split your existing vector first, then transform them into a vector of the mins, then you could use the accumulate function.
So with that in mind, I would maybe do it like this:
std::vector<int> v{ 1,4,2,3};
std::vector<int> v2;
std::vector<int> v3;
std::vector<int> v4;
std::partition_copy(begin(v),
end(v),
back_inserter(v2),
back_inserter(v3),
[toggle = false](int) mutable { return toggle = !toggle; });
std::transform(begin(v2), end(v2), begin(v3), std::back_inserter(v4), [](auto a, auto b)
{
return std::min(a,b);
});
auto sum_of_min_in_pairs = std::accumulate(begin(v4), end(v4), 0);
Note that the code above will have issues if your vector does not have even amount of elements. Otherwise, transform it into a pair, with some default to match the remainder, depending on what you want to achieve.
With the STL website, cppreference.com is your friend. There are also a few books around I would highly recommend.
Effective STL by Scott Meyers
The C++ standard library by Nicolai Josuttis
I would solve this using std::adjacent_difference and std::accumulate:
#include <algorithm> // std::min
#include <iostream>
#include <numeric> // std::adjacent_difference, std::accumulate
#include <vector>
int main()
{
std::vector v{1, 4, 3, 2, 3, 8, 5, 1};
std::adjacent_difference(
v.cbegin(), v.cend(), v.begin(),
[](auto lhs, auto rhs) { return std::min(lhs, rhs); });
auto is_second_elem{true};
std::cout << std::accumulate(cbegin(v), cend(v), 0,
[&is_second_elem](auto acc, auto min) {
is_second_elem = not is_second_elem;
return is_second_elem ? (acc + min) : acc;
})
<< '\n'; // 7
}
Related
I am practicing leetcode easy problem. I want to remove_if from an vector using lambda (for the first time, It is great). I get a negative pointer for new_end.
#include <vector>
#include <iostream>
#include <algorithm>
#include <functional> // std::greater
using namespace std;
int main()
{
vector<int> a = { 2, 7, 11, 15 };
int target = 9;
auto new_end = std::remove_if(a.begin(), a.end(), [&a, target](const int x)
{
return std::count(a.begin(), a.end(), x) > target;
});
a.erase(new_end, a.end());
return 0;
}
There is no error but new_end is a negative pointer value.
std::remove_if(begin, end, pred) returns an iterator pointing at the first element to erase or end if there is no element matching pred. The later is true in your case:
auto new_end = std::remove_if(a.begin(), a.end(),
[&a, target](const int x) { return std::count(a.begin(), a.end(), x) > target; }
);
new_end equals a.end(). This value is printed as garbage by your debugger. But it happens to just works by chance in your case.
As pointed out by multiple commentators, once your predicate has returned true once, the range [a.begin(), a.end) is modified and the last element has an unspecified value1.
This makes std::count(a.begin(), a.end(), x) return unspecified values.
A suggested fix is to make a copy of a before remove_if starts to move things around. This is done by capturing it by value:
auto new_end = std::remove_if(a.begin(), a.end(),
[b=a, target](const int x) { return std::count(b.begin(), b.end(), x) > target; }
);
Initializing the copy to a new name b simply emphasizes that it is a copy.
1) From std::remove_if:
Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition).
I assume to want to remove numbers greater than 9 from vector, Here is the code
vector<int> a = { 2, 7, 11, 15 };
int target = 9;
auto new_end = std::remove_if(a.begin(), a.end(), [](const int x)
{
return x > 9;
});
a.erase(new_end, a.end());
return 0;
The lambda argument 'x' will be provided by remove_if, you don't need to add anything in the capture list
I have a vector of pairs. Suppose it is like this:
vector<pair<int,int>> vec = { {1,12}, {1,5}, {1,6}, {1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };
The pairs are sorted by first element.
Given a pair, I need to find the index of the last pair in the vector whose first element is less than or equal to first element of the given pair. If for that last pair, other pairs lie to its left with the same value of the first element, I need the first of all those pairs:
<4,10> => 4 (vec[4] is <3,9>, the elements with the largest first value less than or equal to 4 are those with first element as 3, and there are 4 pairs with a 3 in the first element, at indices 4-7, so return the first of those pairs)
<0,10> => -1, since no element exists to its right.
<1,6> => 0 (vec[0] is <1,12>. There is no pair whose first element is less than 1, and there are 4 pairs, including <1,6> whose first element is 1. So we need the first of these 4 pairs.)
<23,81> => 12 (vec[12] is <20,8>)
Condition: I need to use only standard algorithms like upper_bound, binary_search and lower_bound. I tried this, but it is failing badly:
vector<pair<int,int>> vec = { {1,12}, {1,5}, {1,6},{1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };
auto i = std::lower_bound(vec.begin(), vec.end(), make_pair<int,int>(4,10),
[](const pair<int,int>& f1, const pair<int,int>& f2) { return f1.first < f2.first; });
cout << i-vec.begin();
Since you want the first pair, you maybe want to combine lower and upper bound?
#include <algorithm>
#include <vector>
#include <utility>
#include <iostream>
using namespace std;
int main()
{
vector<pair <int,int> > vec = { {1,12}, {1,5}, {1,6}, {1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };
auto u_it = std::upper_bound(vec.begin(), vec.end(), make_pair<int,int>(4, 10),
[](const pair<int,int>& f1, const pair<int,int>& f2) { return f1.first < f2.first; });
if(u_it == vec.begin())
cout << "-1\n";
auto l_it = std::lower_bound(vec.begin(), u_it, *prev(u_it),
[](const pair<int,int>& f1, const pair<int,int>& f2) { return f1.first < f2.first; });
cout << l_it - vec.begin() << "\n";
return 0;
}
Output:
Georgioss-MacBook-Pro:~ gsamaras$ g++ -Wall -std=c++0x main.cpp
Georgioss-MacBook-Pro:~ gsamaras$ ./a.out
4
PS - answer updated after WhozCraig's comment:
you want to use it = std::upper_bound(beg,end) to find the first strictly-greater element, and if that answers non-begin, then use std::lower_bound(beg,it) to find the lowest-matching ordinal of the element whose value is pulled from (it-1).
The answer now satisfies all the test cases you have provided (I am not showing it here). Hope that helps! :)
Appendix:
Ref for std::lower_bound, std::upper_bound and std::prev. Please notice how the std::lower_bound call uses std::make_pair without an initializing list, so that it lets the compiler come into play and resolve deduce the type.
std::lower_bound returns the first item greater or equal to the given value
you need to
+1 to the input of std::lower_bound
-1 to the result of std::lower_bound
to find the value (or you can use std::upper_bound)
and use std::lower_bound again to find the right pair
example
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int my_find(const vector<pair<int,int>>& vec, int value){
auto comparer = [](const pair<int,int>& f1, int value) { return f1.first < value; };
auto i = std::lower_bound(vec.begin(), vec.end(), value+1, comparer);
if(i==vec.begin()){return -1;}
i = std::lower_bound(vec.begin(), vec.end(), (i-1)->first, comparer);
return i-vec.begin();
}
int main(){
vector<pair<int,int>> vec = { {1,12}, {1,5}, {1,6},{1,9}, {3,9}, {3,11}, {3,13}, {3,4}, {5,9}, {5,91}, {13,8}, {16,8}, {20,8}, {20,81} };
cout << my_find(vec,-1) << '\n';
cout << my_find(vec,3) << '\n';
cout << my_find(vec,10) << '\n';
cout << my_find(vec,100) << '\n';
}
BTW, you don't need to provide pair to lower_bound
and if you only use lower_bound, you need only one comparer
I have a void function that takes as arguments iterators to the start and the end of a set of points (Setiterator set_begin, Setiterator set_end),a query point to perform some calculations and a iterator to the beginnig of a set of points ( where I am going to add the results)
void computedist(Setiterator set_begin, Setiterator set_end,
Vector const& query_point, DistanceIterator dist_begin )
{
std::transform(set_begin, set_end, dist_begin, calculation);
}
I have read that with std::transform I can do that calculations over the whole set of points, but I don't know how should I define the calculation to be done, as I am new to C++.
In this case, I want to compute the distance of the points to the query point:
I guess that my calculation should look like this
double calc_dist(double query_point, double point_of_the_set){
double dist;
dist = fabs(query_point - point_of_the_set);
return dist;
But I don't know how should I give the arguments to the function, since I am new to working with iterators.
Thank's!
The flavor of std::transform you are calling expects a UnaryOp function to call, to which it passes '*iterator' by const reference and expects a return value of the iterator::value_type which it writes to *dest.
#include <iostream>
#include <algorithm>
#include <vector>
int main() {
using valtype = int;
std::vector<valtype> v1 { 1, 2, 3, 4, 5 };
std::vector<valtype> v2(v1.size());
std::transform(v1.begin(), v1.end(), v2.begin(),
[] (const valtype& in) { return in * 2; });
for (auto& val : v2)
std::cout << val << '\n';
}
Live demo: http://ideone.com/CUUlvA
I need help picking out the least recurring element in an array. I can't think of any robust algorithm, is there any function defined in the c++ library that does that?
If there is an algorithm that you can come up with, please share. Not the code necessarily, but the idea
'Define least recurring' - suppose an array say a[4] holds 2,2,2,4. 4 is the least recurring element
Uses some C++14 features for brevity but easily adapted to C++11:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <unordered_map>
using namespace std;
template <typename I>
auto leastRecurring(I first, I last) {
unordered_map<iterator_traits<I>::value_type, size_t> counts;
for_each(first, last, [&counts](auto e) { ++counts[e]; });
return min_element(begin(counts), end(counts), [](auto x, auto y) { return x.second < y.second; })->first;
}
int main() {
const int a[] = {2, 2, 2, 3, 3, 4};
cout << leastRecurring(begin(a), end(a)) << endl;
}
Using only std goodies (live demo on Coliru):
// Your original vector
auto original = { 2, 2, 2, 4, 4 };
// Sort numbers and remove duplicates (in a copy, because std::unique modifies the contents)
std::vector<int> uniques(original);
std::sort(std::begin(uniques), std::end(uniques));
auto end = std::unique(std::begin(uniques), std::end(uniques));
// Count occurences of each number in the original vector
// The key is the number of occurences of a number, the value is the number
std::map<int, int> population;
for (auto i = uniques.begin(); i != end; ++i) {
population.emplace(std::count(std::begin(original), std::end(original), *i), *i);
}
// The map is sorted by key, therefore the first element is the least recurring
std::cout << population.begin()->second;
Note that in the example you gave, the array is already sorted. If you know that this will always be the case, you can get rid of the call to std::sort.
If two numbers have the same population count, the greater one will be kept.
from collections import Counter
def leastFrequentToken(tokens):
counted = Counter(tokens)
leastFrequent = min(counted, key=counted.get)
return leastFrequent
Essentially, create a map of token:count, find the smallest value in the map and return its key.
Assuming the 'numbers' are ints:
// functor to compare k,v pair on value
typedef std::pair<int, size_t> MyPairType;
struct CompareSecond
{
bool operator()(const MyPairType& left, const MyPairType& right) const
{
return left.second < right.second;
}
};
vector<int> tokens[4] = { 2, 2, 2, 4 };
map<int, size_t> counted;
for (vector<int>::iterator i=tokens.begin(); i!=tokens.end(); ++i)
{
++counted[*i];
}
MyPairType min
= *min_element(counted.begin(), counted.end(), CompareSecond());
int leastFrequentValue = min.second;
C++ translation using these SO question answers:
C++ counting instances / histogram using std::map,
Finding minimum value in a Map
in C++11, assuming your type support strict weak ordering (for std::sort), following may help: https://ideone.com/poxRxV
template <typename IT>
IT least_freq_elem(IT begin, IT end)
{
std::sort(begin, end);
IT next = std::find_if(begin, end, [begin](decltype(*begin) el) { return el != *begin; });
IT best_it = begin;
std::size_t best_count = next - begin;
for (IT it = next; it != end; it = next) {
next = std::find_if(it, end, [it](decltype(*begin) el) { return el != *it; });
const std::size_t count = next - it;
if (count < best_count) {
best_count = count;
best_it = it;
}
}
return best_it;
}
I've been working on learning python and somehow came up with following codes:
for item in list:
while list.count(item)!=1:
list.remove(item)
I was wondering if this kind of coding can be done in c++. (Using list length for the for loop while decreasing its size) If not, can anyone tell me why?
Thanks!
I am not a big Python programmer, but it seems like the above code removes duplicates from a list. Here is a C++ equivalent:
list.sort();
list.unique();
As for modifying the list while iterating over it, you can do that as well. Here is an example:
for (auto it = list.begin(), eit = list.end(); it != eit; ) {
if (std::count(it, eit, *it) > 1)
it = list.erase(it);
else
++it;
}
Hope it helps.
In C++, you can compose something like this from various algorithms of the standard library, check out remove(), find(), However, the way your algorithm is written, it looks like O(n^2) complexity. Sorting the list and then scanning over it to put one of each value into a new list has O(n log n) complexity, but ruins the order.
In general, both for Python and C++, it is often better to copy or move elements to a temporary container and then swap with the original than modifying the original in-place. This is easier to get right since you don't step on your own feet (see delnan's comment) and it is faster because it avoids repeated reallocation and copying of objects.
Here's how I'd do it.
//If we will not delete an element of the list
for (std::list<MyType>::iterator it = MyList.begin(); it != MyList.end();++it)
{
//my operation here
}
//If we will delete an element of the list
for (std::list<MyType>::iterator it = MyList.begin(); it != MyList.end();)
{
std::list<MyType>::iterator itt = it;
++itt;
MyList.erase(it);
it = itt;
}
You can use the size of the list, but it is not comparable to [it] because [it].
Certain features of std:: data classes are enabled or disabled as a design decision. Sure, you can make your own function MyList[int i], but it will lead to a large speed gimp due to the nature of lists.
In C++ you can in some conditions remove elements from a container while iterating over it. This depends on the container and on the operation you want to do.
Currently there are different interpretations of your code snipplet in the different answers. My interpretation is, that you want to delete all the elements which exists more than once in the list.
Here is the solution in C++: it first counts the elements in another container (std::map) and removes the appropriate elements from the list afterwards.
#include <list>
#include <map>
#include <algorithm>
#include <iostream>
int main() {
std::list<int> li { 0, 1, 2, 3, 4, 5, 1, 2, 3, 2, 2 };
// Create count map: element -> count
std::map<int, int> cm;
std::for_each( li.begin(), li.end(), [&cm](int i) { ++cm[i]; } );
// Remove all elements from list with count > 1
std::for_each( cm.begin(), cm.end(),
[&li](std::pair<const int, int> const p) {
if( p.second > 1) {
li.remove( p.first );
}
} );
// Output all elements from remaining list
std::for_each( li.begin(), li.end(),
[](int i) { std::cout << i << std::endl; } );
return 0;
}
I don't know Python but someone said in a comment that a list is equivalent to a C++ vector and it is not sorted, so here goes....
std::vector<int> v{1, 2, 2, 2, 3, 3, 2, 2, 1};
v.erase(std::unique(v.begin(), v.end()), v.end());
v contains {1, 2, 3, 2, 1} after this code. If the goal is to remove all duplicates (not just consecutive duplicates) you'll have to sort the vector first: std::sort(v.begin(), v.end());
std::vector is the container in C++ that is most similar to Python's list, and here's the correct way to modify a vector while iterating it:
template <typename T>
void dedupe(std::vector<T> &vec) {
for (std::vector<T>::iterator it = vec.begin(); it != vec.end(); ) {
if (std::count(vev.begin(), vec.end(), *it) != 1) {
it = vec.erase(it);
} else {
++it;
}
}
}
It's not necessarily the most efficient way to dedupe, but it works.
Using list length for the for loop while decreasing its size
If you insist on using the length rather than the end(), then you can use an index instead of an iterator:
template <typename T>
void dedupe(std::vector<T> &vec) {
for (std::vector<T>::size_type pos = 0; pos != vec.size(); ) {
if (std::count(vec.begin(), vec.end(), vec[pos]) != 1) {
vec.erase(vec.begin() + pos);
} else {
++pos;
}
}
}
I'm assuming that the intention of your Python code is to remove all duplicates, by the way, and that the fact it doesn't is a bug. For example input [2,2,1,3,3,1,2,3], output [1,1,2,3]. If what you said is what you meant, then a direct translation of your code to C++ is:
template <typename T>
void dedupe(std::vector<T> &vec) {
for (std::vector<T>::size_type pos = 0; pos < vec.size(); ++pos) {
T item = vec[pos];
while (std::count(vec.begin(), vec.end(), item) != 1) {
vec.erase(std::find(vec.begin(), vec.end(), item));
}
}
}