Maximum decreasing prefix with iterators - c++

I am writing next permutation algorithm in C++.
It is forbidden to use for and while (we are supposed to do everything with iterators only).
The first step of the algorithm is to get maximum non-increasing suffix. I am strucked, because I don't understand how to find something in vector by condition using only iterators.

You can use std::find or std::for_each defined in algorithm e.g. example using C++14:
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> v{0,1,2,3,5,7};
auto f = std::find(std::begin(v), std::end(v), 5);
if (f != std::end(v)) {
std::cout << "found element 5" << std::endl;
}
std::for_each(
std::begin(v),
std::end(v),
[](int n) {
if (n == 5) {
std::cout << "found element 5" << std::endl;
}
}
);
}

Related

How to check if elements of std::vector<std::string> start with certain sub-string?

I have a very large std::vector v of type std::vector<std::string> v. Now I want to compare which of the elements in the vector start with a certain substring str. What is the fastest possible way to do that?
I was thinking of a for-loop that iteratively compares the start of each element of v with the substring str. I first tried
std::string substring = "bla";
for (long unsigned int i = 0; i < v.size(); i++)
{
if (!strncmp(v[i].c_str(), substring.c_str(), substring.size()))
{
std::cout << "Item found: " << v[i] << std::endl;
}
}
Which is c mixed with c++ and I am not happy with that.
What better alternatives are there?
You can write completely a c++ code.
If you want to find all the elements satisfying the condition, you can not avoid iterating through the entire vector.
But you could use better range-based for-loop instead of index based loop to iterate through the vector, and check wether str.find(substring) == 0(credits #PiotrSkotnicki).
Here is the example code:
(See online)
#include <iostream>
#include <string>
#include <vector>
int main()
{
const std::string substring{ "bla" };
std::vector<std::string> vecString{ {"bllll"}, {"bllll"}, {"blasomething"} };
// iterate through the vector by range based for-loop
// here `auto` deduded to `std::string` as you have vector of strings(i.e. `vecString`)
for (const auto& str : vecString)
{
if (str.find(substring) == 0) {
std::cout << str << " is a match\n";
// do something more with str
}
}
return 0;
}
Alternatively using std::for_each, along with a lambda function you could write the following. Read more about the lambdas here: What is a lambda expression in C++11?
(See online)
#include <algorithm> // std::for_each
std::for_each(std::cbegin(vecString), std::cend(vecString), [&substring](const auto& str)
{
if (str.find(substring) == 0)
{
std::cout << str << " is a match\n";
// do something more with str
}
});
If you are interested only the first match in the vector of string s, making use of standard algorithm std::find_if as follows
#include <algorithm> // std::find_if
const auto iter = std::find_if(std::cbegin(vecString), std::cend(vecString),
[&substring](const auto& str) {
return str.find(substring) == 0;
}
);
if (iter != std::cend(vecString))
{
// do something
}
If you have an unsorted container you can't get better than O(n) in time complexity, which means iterating over the whole container in a linear manner (i.e. for loop). If your container was sorted (ex. std::set instead of std::vector) you would get O(log n) which is a lot better (binary search).
Prior to C++17, I can't come up with a better solution than yours (since creating a substring via std::string::substr means copying the substring unnecessarily). However C++17 introduced std::string_view which doesn't do any copying. There should be no noticable performance difference with compiler optimizations enabled.
std::vector<std::string> v { "abcd", "abcdefg", "aaaabbbb", "abc", "ab"};
std::string_view query = "abc";
for (auto const& str : v)
{
if (str.size() < query.size())
continue;
auto probe = std::string_view(str).substr(0, query.size());
if (query == probe)
std::cout << "Item found: " << str << "\n";
}
Live example
And here is the std::set version for the quicker search:
std::set<std::string> v { "abcd", "abcdefg", "aaaabbbb", "abc", "ab"};
std::string query = "abc";
for (auto it = v.lower_bound(query); it != v.end(); ++it)
{
auto probe = std::string_view(*it).substr(0, query.size());
if (query == probe)
std::cout << "Item found: " << *it << "\n";
else
break;
}
Live example
You can using c++20 std::string_view::start_with:
std::vector<std::string> v = {...};
std::string_view prefix = "bla";
for (std::string_view sv : v)
if (sv.starts_with(prefix))
std::cout << "Item found: " << sv << std::endl;

Python's enumerate for C++ [duplicate]

This question already has answers here:
How to find the index of current object in range-based for loop?
(12 answers)
Closed 4 years ago.
In Python there is enumerate which takes a sequence/iterator and yields pairs of an integer index and the value itself. In C++ I occasionally find myself writing
for (size_t i = 0; i != vector.size(); ++i) {
auto const &elem = vector[i];
// ...
Similar to Python I would like to write
for (auto const &it : enumerate(vector)) {
// it.first is the index (size_t)
// it.second is the element (T const&)
Does such an enumerate exist in either the STL or a common library like Boost?
Yes, this is what Boost's adapators::indexed does.
Their example (which also uses the now-redundant Boost.Assign for terse container initialisation) follows:
#include <boost/range/adaptor/indexed.hpp>
#include <boost/assign.hpp>
#include <iterator>
#include <iostream>
#include <vector>
int main(int argc, const char* argv[])
{
using namespace boost::assign;
using namespace boost::adaptors;
std::vector<int> input;
input += 10,20,30,40,50,60,70,80,90;
for (const auto& element : input | indexed(0))
{
std::cout << "Element = " << element.value()
<< " Index = " << element.index()
<< std::endl;
}
return 0;
}
Nothing in the standard library, though it's not hard to write.
Here is an example using range-v3. A bit more verbose than a handcrafted solution, but it's nice IMHO how you can assemble such a range from existing views.
#include <range/v3/view/indices.hpp>
#include <range/v3/view/zip.hpp>
using namespace ranges;
std::vector<int> vec{42, 43, 44};
for (const auto& idxAndValue : view::zip(view::indices, vec))
std::cout << ideAndValue.first << " : " << idxAndValue.second << "\n";;
Another way that only works:
with references to elements, and
array-based containers, and
elements do not overload operator&
for(auto const &it : vector) {
size_t index = &it - vector.data();
}
Here's a version using an higher-order function. I like it because it's simple to implement and doesn't require you to know the nuances of structured bindings. It also doesn't require any extra dependency.
template <typename Container, typename F>
void enumerate(Container&& c, F&& f)
{
std::size_t i = 0;
for(auto&& x : std::forward<Container>(c))
{
f(i++, forward_like<Container>(x));
}
}
(Where forward_like moves x if Container is an rvalue.)
Usage:
enumerate(std::vector{'a', 'b', 'c'}, [](auto index, auto x)
{
std::cout << index << ": " << x << '\n';
});
Prints:
0: 'a'
1: 'b'
2: 'c'
live example on wandbox.org
C++11 compliant version: live example on wandbox.org

I want to reverse the values of map and print it using range based for loop.

I have done the programming but it is not reversing. I have used a different map to put the values in reverse order,but it still shows the same. My main question was to traverse backward and print the values using range based loop.
#include "stdafx.h"
#include <iostream>
#include<conio.h>
#include <stdio.h>
#include<vector>
#include<map>
#include<utility>
#include<set>
map<int, int>m1;
for (int i = 1; i <= 100; ++i)
{
m1.insert({ i,i });
}
for (const auto &y :m1)
{
cout <<"("<< y.first << " "<<y.second << ")" <<" " ;
}
cout << endl << endl;
map<int, int>m2;
map<int, int>::reverse_iterator iter;
for (auto iter = m1.rbegin(); iter != m1.rend(); ++iter)
{
m2.insert({ iter->first,iter->second });
}
for (const auto &y : m2)
{
cout << "(" << y.first << " " << y.second << ")" << " ";
}
As Some Programmer Dude pointed out, but for the completeness of my answer, a std::map is sorted on the key, no matter what order you insert the elements. One option would be to create a new map with the opposite sorting, but that doesn't seem to be what you really want.
It seems you know how about reverse iterators, but not how to get at them when using range-based for. Since it operates on a range, i.e. some type that provides begin and end iterators, you need to create some wrapper around your map that provides this.
Here's a general one I just put together than works in C++11. It won't cover every possible case, and can be made a bit neater in C++14, but it will work for you.
#include <iostream>
#include <iterator>
// The wrapper type that does reversal
template <typename Range>
class Reverser {
Range& r_;
public:
using iterator_type = std::reverse_iterator<decltype(std::begin(r_))>;
Reverser(Range& r) : r_(r) {}
iterator_type begin() { return iterator_type(std::end(r_)); }
iterator_type end() { return iterator_type(std::begin(r_)); }
};
// Helper creation function
template <typename Range>
Reverser<Range> reverse(Range& r)
{
return Reverser<Range>(r);
}
int main()
{
int vals[] = {1, 2, 3, 4, 5};
for (auto i : reverse(vals))
std::cout << i << '\n';
}
This outputs:
$ ./reverse
5
4
3
2
1
(You may also find libraries that provide a similar adapter; Eric Niebler is working on a ranges library for The Standard.)
Also, please reconsider your use of what are often considered bad practices: using namespace std; and endl (those are links to explanations).
Here's an example of iterating backward through a std::map:
#include <iostream>
#include <map>
#include <string>
int main() {
std::map<int, int> m;
m[1] = 1;
m[2] = 2;
m[3] = 3;
for (auto iter = m.rbegin(); iter != m.rend(); ++iter) {
std::cout << iter->first << ": " << iter->second << std::endl;
}
}
If you are pre-C++11, you'll just need to spell out auto, which is:
std::map<int, int>::reverse_iterator
If you're using boost, you can use a range-based for loop with a reverse adapter:
#include <boost/range/adaptor/reversed.hpp>
for (auto& iter : boost::adaptors::reverse(m)) {
std::cout << iter.first << ": " << iter.second << std::endl;
}
If you only need to print the elements in the map in reverse order,you don't need another map for it,you can do this:
std::map<int, int>::reverse_iterator iter;
for (iter = m1.rbegin(); iter != m1.rend(); ++iter)
{
std::cout << "(" << iter->first << " " << iter->second << ")" << " ";
}

STL correct use of find_if() to print out odd numbers

How can I possibly make use of the find_if algorithm from STL to find and print out odd numbers from a vector?
Let me just give you an example of what I'm on about:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool isOdd(int x)
{
return x%2 == 0;
}
int main(void)
{
int tab[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
vector<int> myVec(tab, tab + sizeof(tab)/sizeof(tab[0]));
vector<int>::iterator it;
// Printing out all numbers
cout << "Vector contains the following numbers: " << endl;
for(it = myVec.begin(), it != myVec.end(), ++it)
{
cout << *it << ' ';
}
// An unsuccessful attempt to print out odd numbers while using find_if and while loop
vector<int>::iterator bound = find_if(myVec.begin(), myVec.end(), isOdd);
while(bound != myVec.end())
{
cout << *bound << ' ';
}
}
What is wrong with while loop? I guess it's the core problem of my code.
I'm assigning whatever the find_if function will return to the iterator, and then I simply can't figure out how to cherry-pick odd values from the vector ;(
The problem is that you are not advancing the iterator in your loop:
while(bound != myVec.end())
{
cout << *bound << ' ';
bound = find_if(bound+1, myVec.end(), isOdd);
}
In C++11 you can use std::next(bound) instead of bound+1.
Also, your isOdd returns true when the number is even. It should be
bool isOdd(int x)
{
return x%2 != 0;
}
Demo.
Just adding that for this use I'd just use std::copy_if:
std::copy_if(myVec.begin(), myVec.end(),
std::ostream_iterator<int>(std::cout, " "), isOdd);
Similarly, the first for loop in your code (and those should be semicolons, not commas) can be replaced with std::copy:
std::copy(myVec.begin(), myVec.end(), std::ostream_iterator<int>(std::cout, " "));
Demo.

C++ - Iterating over std::vector<> returned from find_if

I'm learning C++, so I feel like this should be a very simple answer - but I can't seem to find it. So I apologize in advance if it's naive.
I have a std::vector<int> of of values, and I am trying to find the indices of the odd values.
I am following the code from here:
(repeated below):
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
bool IsOdd (int i) {
return ((i%2)==1);
}
int main () {
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "The first odd value is " << *it << '\n';
return 0;
}
This example prints the first odd value. How could I extend this to give me the index values for each of the odd values in myvector? Is this the correct approach?
// find_if example
#include <iostream> // std::cout
#include <algorithm> // std::find_if
#include <vector> // std::vector
bool IsOdd (int i) {
return ((i%2)==1);
}
int main () {
std::vector<int> myvector;
myvector.push_back(10);
myvector.push_back(25);
myvector.push_back(40);
myvector.push_back(55);
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "ODD values are: " << std::endl;
while(it != myvector.end() ){
std::cout << *it << " in position " << (it - myvector.begin()) << '\n';
it = std::find_if (++it, myvector.end(), IsOdd);
}
return 0;
}
EDIT: Changed it+1 to ++it see #David Rodríguez - dribeas comment below.
You can increment it and use it as a starting point to iterate further:
std::cout << "odd values: ";
auto it = myvector.begin();
while(it != myvector.end())
{
it = std::find_if (it, myvector.end(), IsOdd);
if(it == myvector.end()) break;
std::cout << *it << ' ';
++it;
}
std::cout << endl;
A much more algorithm oriented approach, makes use of copy_if, having an output vector as a result container:
std::vector<int> results;
std::copy_if(myvector.begin(), myvector.end(), std::back_inserter(results), IsOdd);
Now results contains the odd values. (Note the back:inserter is in the <iterator> header)
You can find the index of a vector iterator (and, more generally, any random-access iterator) by subtracting the start of the sequence:
std::cout << "The index is " << (it - myvector.begin()) << '\n';
Even more generally, there is a std::distance function which can give you the distance between forward iterators. You could use that, for example, if your container were a list; but you probably wouldn't want to, since it would be much slower.
To find all the odd numbers, you'll need a loop to call find again, starting from the element after the one you just found.
Change these two lines:
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
std::cout << "The first odd value is " << *it << '\n';
into something like:
std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
while ( it != myvector.end() ) {
std::cout << "The next odd value is " << *it << '\n';
it = std::find_if (++it, myvector.end(), IsOdd);
}
You'll need a loop. The iterator-algorithm design of the standard library makes this pretty easy:
#include <iterator>
for (auto it = myvector.begin();
(it = std::find_if(it, myvector.end(), IsOdd)) != myvector.end(); )
{
std::cout << *it << " at index " << std::distance(myvector.begin(), it) << "\n";
}
A nice compact solution could be:
#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> const v{1,4,9,11,2,7,8};
std::cout << "Odd values at indices";
for(auto b=begin(v), i=b, e=end(v);
(i=find_if(i,e,[](int a){return a%2==1;})) != e;
++i)
std::cout << ' ' << distance(b,i);
std::cout.flush();
}