I am new to C++. I am trying to find the index of the element if there is a subset in the vector.
I have my code below.. Please help me with the solution.
#include <iostream>
#include <vector>
#include <algorithm>
int main()
{
std::vector<uint8_t> v = { 1,2,3,4,0,6,7,8,4,5,6 };
int key = 4;
std::vector<uint8_t>::iterator itr = std::find(v.begin(), v.end(), key);
if (itr != v.cend()) {
uint8_t index = std::distance(v.begin(), itr);
if ((++index == 5) && (++index == 6))
std::cout << "Element present at index " << index-2;
else
continue;
}
else {
std::cout << "Element not found";
}
return 0;
}
In the above code, I want to print the index of the element '4' if 4,5,6 are consecutive elements.
Output : 8
You must replace your first if by a while with the same test, replace both of your ++index by *(++itr), not subtract 2 to index before printing it, and replace your last else by if(itr == v.cend())to get the output you want.
Note that this code doesn’t work anymore if you change the expected elements to find from {4,5,6} to {4,4,6} for example, so I would suggest you to change the general approach of your problem if you want to generalize it.
Related
I'm trying to remove duplicate combinations of integer vectors stored in a list using a hash table. Iterating over each integer vector in the list, I:
Calculate the hash_value (thash)
See if the hash value is already in the hash table (pids)
If it's in the hash table, erase that vector from the list.
Otherwise, add that value to the hash_table and increment the list
iterator
Print statements seem to confirm my logic, but the loop hangs at the fourth step of iteration. I've commented the it++ and vz.remove(it) that cause the problem and only show the logic in the code below. The code is also available through ideone: https://ideone.com/JLGA0f
#include<iostream>
#include<vector>
#include<list>
#include<cmath>
#include<unordered_set>
using namespace std;
double hash_cz(std::vector<int> &cz, std::vector<double> &lprimes) {
double pid = 0;
for(auto it = cz.begin(); it != cz.end(); it++) {
pid += lprimes[*it];
}
return pid;
}
int main(){
// create list of vectors
std::list<std::vector<int>> vz;
vz.push_back({2,1});
vz.push_back({1,2});
vz.push_back({1,3});
vz.push_back({1,2,3});
vz.push_back({2, 1});
// vector of log of prime numbers
std::vector<double> lprimes {2, 3, 5, 7};
for (auto it = lprimes.begin(); it != lprimes.end(); it++) {
*it = std::log(*it);
}
std::unordered_set<double> pids;
double thash;
for (auto it = vz.begin(); it != vz.end(); ) {
thash = hash_cz(*it, lprimes);
std::cout << thash << std::endl;
// delete element if its already been seen
if (pids.find(thash) != pids.end()) {
std::cout << "already present. should remove from list" << std::endl;
// vz.erase(it);
}
else {
// otherwise add it to hash_table and increment pointer
std::cout << "not present. add to hash. keep in list." << std::endl;
pids.insert(thash);
// it++;
}
it++;
}
for (auto it = vz.begin(); it != vz.end(); it++) {
for (auto j = it -> begin(); j != it -> end(); j++) {
std::cout << *j << ' ';
}
std::cout << std::endl;
}
return 0;
}
Problem is this line of code:
vz.erase(it);
It keeps iterator where it was ie leaves it invalid. It should be either:
vz.erase(it++);
or
it = vz.erase( it );
Note: std::unoredered_set::insert() return value tells you if insert was succesfull or not (if the same value element is there already), you should call it and check result. In your code you do lookup twice:
if (pids.insert(thash).second ) {
// new element added
++it;
} else {
// insertion failed, remove
it = vz.erase( it );
}
As std::list provides remove_if() your code can be simplified:
vz.remove_if( [&pids,&lprimes]( auto &v ) {
return !pids.insert( hash_cz(v, lprimes) ).second );
} );
instead of whole loop.
If the element has already been seen, you erase() the it node and then increment it at the end of the loop: undefined behaviour. Try erase(it++) instead.
If the element has not been seen, you increment it and then do it again at the end of for, yielding UB if it was end() - 1 as it moves past end.
So i need to be able to do this in c++. what i was able to do is using "abaaacc" as a string and i got the right answer, but i don't know how to solve it when "a b a a a c c" are in a linked list. can someone help me with a code:
here is my code
#include <iostream>
using namespace std;
const int SIZE=20;
int main ()
{
int numbs[SIZE], value, idx,n;
cout<<"PLease enter size of an array"<<endl;
cin>>n;
cout << "Please enter in a series of numbers "<<endl;
for(idx = 0; idx < n; idx++)
cin >>numbs[idx];
cout<< numbs[0] << " ";
for (int i = 1; i < n; i++)
{
bool matching = false;
for (int j = 0; (j < i) && (matching == false); j++)if (numbs[i] == numbs[j]) matching = true;
if (!matching) cout<< numbs[i] << " ";
}
}
now i want it to remove the duplicate adjacent and give me 1 copy of it
like the ex but using numbers so how can i be able to edit my code to do that.
I had some time and so I tried to solve this.
It is indeed a tricky thing. You need to take care of the edge cases first and last item, and 1-2 item lists.
In between you need to iterate with three iterators at the same time to find the unique item in the middle of these subsets. And as you are dealing with a list, you need to work around the missing random access iterators.
I'm more used to Python these days, where complex iteration is comfortable and you can get away with zips and slices nicely in this case. Maybe the new ranges could have been used to nicen up this code. Maybe I'll try this some time.
#include <list>
#include <iostream>
std::list<char> remove_adjacent_duplicates(std::list<char> input) {
std::list<char> output;
std::list<char>::iterator first = input.begin();
if (first == input.end()) {
// no first, item, exit
return output;
}
// let second point to second element
std::list<char>::iterator second = input.begin();
++second;
if (second == input.end()) {
// no second item, insert first, then exit
output.push_back(*first);
return output;
}
// check first item
if (*first != *second) {
// first and second are different, insert first
output.push_back(*first);
}
// let third point to third item
std::list<char>::iterator third = input.begin();
++third; ++third;
// check items up until the last
while (third != input.end()) {
if (*first != *second && *second != *third) {
// the second item neither equals the first, nor the third
// insert second
output.push_back(*second);
}
// increment iterators
++first; ++second; ++third;
}
// finally, check the last item
if (*first != *second) {
// the last two items differ, insert the latter
output.push_back(*second);
}
// done
return output;
}
void test_case(std::list<char> l) {
std::list<char> output = remove_adjacent_duplicates(l);
for (char i : l) {
std::cout << i << ' ';
}
std::cout << " -> ";
for (char i : output) {
std::cout << i << ' ';
}
std::cout << '\n';
}
int main() {
test_case({'a'});
test_case({'a', 'b'});
test_case({'a', 'b', 'a', 'a', 'a', 'c', 'c'});
}
The output is:
$ g++ test.cc -std=c++11 && ./a.out
a -> a
a b -> a b
a b a a a c c -> a b
Simple enough. First you std::sort the container and then you use std::unique (combined with erase) to remove all but one instance of each value.
I have to process element from a deque (first to last), but at each iteraton I need to use one element and the next too. So I'm trying to write a for loop that starts with mydeque.begin() and finishes at mydeque[mydeque.size()-1]. Also; I would like to know if my iterator deque::iterator it has a next method (it->next()), to make operations like *it - *it->next(). Thank you very much.
Here's how:
#include <deque>
#include <iostream>
int main() {
std::deque<int> test = {1,2,3,4,5,6,7,8};
for(auto i = test.begin(); i != test.end(); i++) {
auto next = std::next(i);
std::cout << *i << *next << std::endl;
if(next==test.end())
{
//Do something. This is the last element.
break;
}
}
}
EDIT: Watch out for deques with only one element. Do this by performing a check such as if(test.begin()==test.end()).
EDIT: My initial solution was indeed a bit error prone and unprecise.
This can easily be done using iterators, see this little example:
#include <deque>
#include <iostream>
int main() {
std::deque<int> test = {1,2,3,4,5,6,7};
for(auto i = test.begin(); i != test.end(); ++i) {
auto next = std::next(i);
if(next != test.end()) {
std::cout << *i << " " << *next << std::endl;
}
}
}
You can simply increment the iterator by 2 and use std::next to also pick the following item (since the offset of std::next defaults to 1).
I'm new to C++ so this might be a simple problem but I'm working my way through the C++ book by Stanley Lippman and there's this exercise where you're supposed to write a very basic search function for a vector of ints. Basically just incrementing the iterator until you find what you're looking for and then return an iterator to the element.
My first question is, in the book it says "Don't forget to handle the case where the element can't be found" - what would you do in a case like that? In java I would return a null but I guess that's not okay in C++ (a nullptr?)?
Second question is, why doesn't it work? I thought that if I can't find it, I'll just return the end()-iterator as it's one element behind the last one (thus, not pointing to an element in the vector) but I can't get the comparing to work, it says "Found!" on every number when I try it.
#include <vector>
#include <iterator>
#include <iostream>
const std::vector<int>::iterator
search (std::vector<int> v, const int find) {
auto beg = v.begin();
const auto end = v.end();
while (beg != end) {
if (*beg == find) {
return beg;
}
++beg;
}
return beg; // This can only be reached if beg = v.end()?
}
int
main () {
std::vector<int> v;
v.insert(v.end(), 2);
v.insert(v.end(), 5);
v.insert(v.end(), 10);
v.insert(v.end(), 7);
v.insert(v.end(), 12);
for (int i = 0; i < 16; ++i) {
std::vector<int>::iterator b = search(v, i);
std::cout << i;
if (std::distance(b, v.end()) == 0) {
std::cout << " not found!";
} else {
std::cout << " found!";
}
std::cout << std::endl;
}
return 0;
}
with output as follows:
$ ./a.exe
0 found!
1 found!
2 found!
3 found!
4 found!
5 found!
6 found!
7 found!
8 found!
9 found!
10 found!
11 found!
12 found!
13 found!
14 found!
15 found!
When you call the function, you are passing the vector by value, so it makes a copy. The iterators for this copy will not be the same as the ones in the original vector so the comparison fails. To fix this, pass the vector by constant reference:
search( const std::vector<int>& v, const int find )
To answer your first question, yes, returning the end() iterator is how you indicate the value was not found. This is how std::find() works:
If no such element is found, the function returns last.
I have two questions but they are interlinked.:
part:a->
I have been trying to display the elements of vector in reverse order. But nothing is working. I have used iterotar like;
for (it=vec.end(); it!=vec.begin(); --it){
// it is iterator not reverse_iterator.
// do work
}
P.S I am not much familiar with iterators. I have used them for the first time today to
display elem in reverse order.
also tried;
for (int i=vec.size(); i!=0; i--){
//display
}
No matter what I do it always display the elem in same order as they are present i.e not in the reverse order.
part_b->
Is there any way that I can store the output of a recursive function direct into a vector. like the code is:
I know this does not work. I have tried but just giving you an idea
what I am upto.
#include <iostream>
using namespace std;
#include "vector"
int func(int num);
vector <int> vec;
int main() {
int num=34;
// I know this would not work. But is there any possibilitiy that
// I can store the output in a vector.
vec = binary(num);
// trying to display the vector.
for (int i=vec.size();i!=0;i--) {
cout<<vec[i]<<" ";
} // not working for reverse display.
} //main.
int func(int num) {
if (num==1) {
//vec.push_back(1);
return 1;
}
else if(num==0) {
//vec.push_back(0);
return 0;
}
else {
//vec.push_back(input%2);
return binary(input/2);
}
} //func.
I hope you do unnderstand the question. if I am able to do the part b the there is no need to reverse the elem of the vector.
The standard solution uses reverse iterators:
for (auto it = v.rbegin(); it != v.rend(); ++it)
{
if (it != v.rbegin()) { std::cout << ' '; }
std::cout << *it;
}
Alternatively, you can use indices, but keep the "reversal" idiom and increment the index:
for (std::size_t i = 0; i != v.size(); ++i)
{
if (i != 0) { std::cout << ' '; }
std::cout << v[v.size() - i - 1];
}
Note that reverse iterators are literally just doing something very similar to the explicit loop under the hood. In particular, the base() member function of a reverse iterator gives you the corresponding ordinary iterator offset by one, just as we have a - 1 in the index computation. (E.g. rbegin() is just end() under the hood, but decrements by one upon dereferencing.)
Use reverse iterators:
for (auto it = vec.crend(); it != vec.crbegin(); ++it) {
std::cout << *it << ' ';
}
std::cout << '\n';
Part A
Assuming you haven't got access to C++11:
vector<int>::const_reverse_iterator it;
for (it=vec.rbegin(); it!=vec.rend(); ++it)
{
// do work
}
Part B
It looks very much like you're trying to display a number in binary. Unfortunately the standard flags on ostream only allow hex, decimal or octal as far as I'm aware, but can I suggest a simpler way of doing this?
#include <bitset>
bitset< sizeof(int) << 3 > b(34);
cout << b << endl;
Which gives:
00000000000000000000000000100010
The rather ugly looking sizeof(int) << 3 is just a way of getting the size of an int in bits to avoid truncation.
I wrote little program which may help. Maybe your vector is empty?
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char *argv[])
{
vector<int> vec;
vec.insert(vec.begin(), 1, 1);
vec.insert(vec.begin(), 1, 2);
vec.insert(vec.begin(), 1, 3);
vector<int>::iterator i;
for (i = vec.end(); i != vec.begin(); --i)
{
cout << *i;
}
cout << *i;
return 0;
}