I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}
Related
I have an algorithm which generates combinations from entries of a container and I want to find the combination which minimizes a cost function:
struct Vec { double x; double y; };
double cost( Vec a, Vec b ) {
double dx = a.x - b.x;
double dy = a.y - b.y;
return dx*dx + dy*dy;
}
pair<Vec,Vec> get_pair_with_minimum_cost ( vector<Vec> inp, double (*cost_fun)(Vec,Vec) )
{
pair<Vec,Vec> result;
double min_cost = FLT_MAX;
size_t sz = inp.size();
for(size_t i=0; i<sz; i++) {
for (size_t j=i; j<sz; j++) {
double cost = cost_fun(inp[i], inp[j]);
if (cost < min_cost) {
min_cost = cost;
result = make_pair(inp[i], inp[j]);
}
}
}
return result;
}
vector <Vec> inp = {....};
auto best_pair = get_pair_with_minimum_cost ( inp, cost );
Unfortunately, get_pair_with_minimum_cost() does 2 jobs:
generates the combinations
gets the minimum element
I could break them in two functions, like:
the generator:
template <class Func>
void generate_all_combinations_of( vector<Vec> inp, Func fun )
{
size_t sz = inp.size();
for(size_t i=0; i<sz; i++) {
for (size_t j=i; j<sz; j++) {
fun(make_pair(inp[i], inp[j]));
}
}
}
and then use std::min_element on the output of the generator, i.e.
vector<Vec> inp = {....};
vector<pair<Vec,Vec>> all_combinations;
generate_all_combinations_of(inp, [&](vector<pair<Vec,Vec>> o){all_combinations.push_back(o); } );
auto best_pair = *min_element(all_combinations.begin(), all_combinations.end(), cost);
but I do not want the pay the cost of creating and extra container with temporary data (all_combinations).
Questions:
Can I rewrite the generate_all_combinations_of() such that it uses yield or the new std::ranges in such a way that I can combine it with STL algorithms such as find_if, any_of, min_element or even adjacent_pair ?
The great thing about this 'generator' function is that it is easy to read, so I would like to keep it as readable as possible.
NB: some of these algorithms need to break the loop.
What is the official name of combining entries this way?
It this the combinations used in 'bubble-sort'.
Here's how I would write the function in c++20, using range views and algorithms so that there isn't a separate container that stores the intermediate results:
double get_minimum_cost(auto const & inp)
{
namespace rs = std::ranges;
namespace rv = std::ranges::views;
// for each i compute the minimum cost for all j's
auto min_cost_from_i = [&](auto i)
{
auto costs_from_i = rv::iota(i + 1, inp.size())
| rv::transform([&](auto j)
{
return cost(inp[i], inp[j]);
});
return *rs::min_element(costs_from_i);
};
// compute min costs for all i's
auto all_costs = rv::iota(0u, inp.size())
| rv::transform(min_cost_from_i);
return *rs::min_element(all_costs);
}
Here's a demo.
Note that the solution doesn't compare the cost between same elements, since the cost function example you showed would have a trivial result of 0. For a cost function that doesn't return 0, you can adapt the solution to generate a range from i instead of i + 1. Also, if the cost function is not symmetric, make that range start from 0 instead of i.
Also, this function has UB if you call it with an empty range, so you should check for that as well.
There is http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2168r0.pdf who's development I would follow
If you are using MSVC, and can use their experimental/generator (not sure if others support it yet), you can use
std::experimental::generator<std::size_t> Generate(std::size_t const end){
for(std::size_t i = 0; i < end; ++i)
co_yield i;
}
int main(){
auto vals = Generate(22);
auto const result = *std::min_element(std::begin(vals),std::end(vals));
std::cout <<'\n' << " " << result;
}
Here you would need to modify the Generate function to Yield a pair/or to yield cost
(My recommendation would be to Keep things simple and yield the cost)
Then use vals to find min_cost
Ranges
Based on what I can find about the Ranges Proposal, it works on the basis of std::begin and std::end both of which experimental::generator provides
So it should probably work
Here's how I would write the function in c++17, using algorithms' min_element function, with no need for a separate container that stores the intermediate results. I know you were looking for a c++20 solution, but this code does work fine under c++20, and perhaps it gives you some ideas about adapting functions to ranges when the range isn't just one of the ranges supplied by c++20's ranges library.
// TwoContainerRanger is an iterable container where the iterator consists
// of two indices that match the given filter, and whose iterators, when
// dereferenced, return the result of calling func with the
// elements of the two containers, at those two indices.
// filter can be nullptr.
template <typename Container1, typename Container2, typename Func>
struct TwoContainerRanger {
Container1 &c1;
Container2 &c2;
const Func &fun;
bool (*restriction)(size_t i1, size_t i2);
TwoContainerRanger(Container1 &container1, Container2 &container2,
bool (*filter)(size_t i1, size_t i2), const Func &func)
: c1(container1), c2(container2), fun(func), restriction(filter) {}
struct Iterator {
const TwoContainerRanger *gen;
size_t index1, index2;
auto &operator++() {
do {
if (++index1 == gen->c1.size()) {
if (++index2 == gen->c2.size()) {
// we leave both indices pointing to the end
// to indicate that we have reached the end.
return *this;
} else {
index1 = 0u;
}
}
} while (gen->restriction && gen->restriction(index1, index2) == false);
return *this;
}
bool operator==(const Iterator &other) const = default;
bool operator!=(const Iterator &other) const = default;
auto operator*() const {
return gen->fun(gen->c1[index1], gen->c2[index2]);
}
};
Iterator begin() {
Iterator b{this, size_t(0) - 1, 0u};
return ++b; // automatically applies the restriction
}
Iterator end() { return Iterator{this, c1.size(), c2.size()}; }
};
Calling it looks like this:
int main() {
std::array<Vec, 5> ar = {Vec{0, 0}, Vec{1, 1}, Vec{3, 3}, Vec{7, 7},
Vec{3.1, 3.1}};
TwoContainerRanger tcr{ar, ar, Triangle, cost};
auto result = std::min_element(tcr.begin(), tcr.end());
std::cout << "Min was at (" << result.index1 << "," << result.index2
<< "); cost was " << *result << '\n';
}
Here's a demo.
I have a vector std::vector. I would like to iterate the vector for finding a match, if found would like to return the pointer to the element as below:
const int * findint(std::vector <int> &v, int a)
{
std::vector<int>::const_iterator i1,i2;
i1 = v.begin();
i2 = v.end();
for(;i1 != i2;++i1) {
if(a== *i1) {
return(i1);
}
}
return(0);
}
This was compiling and working ok with GNU g++2.95.3 compiler but not compiling with GNU g++ 4.9.2 and giving the following error:
error: cannot convert 'std::vector<GenFld>::const_iterator {aka __gnu_cxx::__normal_iterator<const int*, std::vector<int> >}' to 'const int*' in return
[exec] return(i1);
Need help.
This will solve your problem:
const int * findint(const std::vector <int> &v, int a){
auto i1 = v.cbegin();
auto i2 = v.cend();
for(;i1 != i2;++i1){
if(a == *i1){
return &*i1;
}
}
return nullptr;
}
Edit: Note that I changed iterators to cbegin and cend also the vector is now passed as const.
However, the right way to do it IMO (with respect to nathanoliver note):
auto it = std::find(v.cbegin(),v.cend(),value);
decltype(&*it) ptr;
if(it==v.cend()){
ptr = nullptr;
}
else{
ptr = &*it;
}
You have to be careful when using this. Pointers and Iterators may be invalid after any push_back or insert or erase on the vector, for a comprehensive list see Iterator invalidation rules. If you want to keep a clue to reach some item later. and if you can guarantee that only adding to the back of the vector will happen, you may keep the index of the item using:
auto it = std::find(v.cbegin(),v.cend(),value);
size_t index;;
if(it==v.cend()){
//do something
}
else{
index = std::distance(v.cbegin(),it)
}
Use v.data():
const int * findint(const std::vector <int> &v, int a)
{
const int * const b = v.data();
const int * const e = b + v.size();
const int * const r = std::find(b, e, a);
return (r == e) ? nullptr : r;
}
You could do something like this
auto i1 = std::find(v.begin(), v.end(), a);
if(i1 != v.end())
{
index = std::distance(v.begin(), i1);
return(&v[index])
}
else
{
return NULL;
}
I'm writing program for graphs. In this program I have a method which has to return vertices inside the weak component originating at vertex. I am getting: Error "vector iterators incompatible"
struct graph {
std::vector <std::vector<int>> gr;
};
std::vector<int> weak_component(const graph& g, int vertex) {
std::vector<int> ret;
stack<int> s;
s.push(vertex);
vector<int>::iterator j;
bool* used = new bool[g.gr.size()];
while (!s.empty()) {
int hodn=s.top();
s.pop();
used[hodn] = true;
for (j == g.gr[hodn].begin(); j != g.gr[hodn].end(); j++) {
if (!used[*j]) {
s.push(*j);
ret.push_back(*j);
}
}
}
return ret;
}
What's wrong with it?
Since you are taking g as a const graph&, this means g.gr is treated as const inside your function. begin on a const vector<T> returns a const_iterator. (also you used == instead of = for assignment)
for (std::vector<int>::const_iterator j = g.gr[hodn].begin(); ...)
But with C++11 or newer you may as well use auto to avoid this
for (auto j = g.gr[hodn].begin(); ...)
or a range-based for:
for (auto&& e : g.gr) {
if (!used[e]) {
s.push(e);
ret.push_back(e);
}
}
I have this function that is suppose to return all possible permutation of integers inside the vector. The code is based from an existing code that does a permutation of strings, I tried to remodeled it to work on vectors but apparently, they dont work similarly as I thought..
I'll appreciate any help that you could offer thanks;
vector<vector<int>> permute(vector<int> &v1, vector<int> &v2){
vector<vector<int>> v;
if( v1.empty() )
{
v.push_back(v2);
return v;
}
for(auto it = v1.begin(); it != v1.end(); it++){
vector<int> temp1 = v1;
temp1.erase(it); //there's a runtime error on this line
vector<int> temp2 = v2;
temp2.push_back(*it);
permute(temp1, temp2);
}
return v;
}
This is the original code that permutes a string.
void string_permutation( std::string& orig, std::string& perm )
{
if( orig.empty() )
{
std::cout<<perm<<std::endl;
return;
}
for(int i=0;i<orig.size();++i)
{
std::string orig2 = orig;
orig2.erase(i,1);
std::string perm2 = perm;
perm2 += orig.at(i);
string_permutation(orig2,perm2);
}
}
Here you go:
template < typename T>
void vec_permute( std::vector<T> &orig, std::vector<T> &perm)
{
if(orig.empty())
{
for( auto &x : perm)
std::cout<<x;
std::cout<<"\n";
return;
}
for(typename std::vector<T>::size_type i=0;i <orig.size();++i)
{
std::vector<T> orig2(orig);
orig2.erase(std::find(orig2.begin(),orig2.end(),orig.at(i)));
std::vector<T> perm2(perm);
perm2.push_back(orig.at(i));
vec_permute(orig2,perm2);
}
}
Demo: http://coliru.stacked-crooked.com/a/01ded4b778aa4165
Iterators can only be used with the container that you instanciated them with
#include <vector>
int main()
{
vector <class> abc;
}
when pressing some key
vector.push_back(class());
each loop
draw(vector)// what should the parameters be?
draw function
draw(vector,sizeofvector)
{
for (int x=0;x< sizeofvector;x++)
{draw vector[x];}
}
how should the parameters look? should i be passing an *abc?
In modern C++ this can be answered without correcting your errors:
for (const auto & x : vector) { draw(x); }
Alternatively (still in C++11):
for (auto it = vector.cbegin(), end = vector.cend(); it != end; ++it)
{
draw(*it);
}
This might work in C++98/03, too:
for (std::size_t i = 0, end = vector.size(); i != end; ++i) { draw(vector[i]); }
If you don't intend to modify the vector, you usually pass it by const reference.
void draw(const std::vector<T>& v)
{
for (int x = 0; x < v.size(); x++)
{
// draw v[x];
}
}
You can also use iterators (this is often preferable).
void draw(const std::vector<T>& v)
{
for (std::vector<T>::const_iterator x = v.begin(); x != v.end(); ++x)
{
// draw *x;
}
}
The reason you don't pass it by value (draw(std::vector<T> v)) is because that would cause the entire vector to be copied every time you call the function, which is obviously incredibly inefficient. References mean that you just refer to the existing vector rather than creating a new one.
std::vector is the type. You need to pass in an instance, so in your case:
draw(abc);
I also agree that your function should have prototype:
void draw( const std::vector<class> & v );
#include <algorithm>
#include <vector>
#include <iostream>
void addOne(int& value)
{
value++;
}
void print(int& value)
{
std::cout << value;
}
int main()
{
std::vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
myVector.push_back(3);
std::for_each(myVector.begin(), myVector.end(), addOne);
std::for_each(myVector.begin(), myVector.end(), print);
}
Output: 234
wrote by hand, compiler errors possible