c++ vector clear() doen't work - c++

string str;
vector<int> v(200,0);
getline(cin, str);
for (int i = 0 ; i < str.size(); i++) {
v[str[i]-97]++;
}
for (int i = 0; i < 26; i++) {
printf("%d ", v[i]);
}
v.clear();
cout << endl;
for (int i = 0; i < 26; i++) {
printf("%d ", v[i]);
}
I want to know the number of each alphabet and clear vector v. But it doesn't work. what is the reason?

Calling v.clear() resizes the vector to zero elements. If you want to set the elements to a specific value (here 0), keeping the original size, you may use
v.assign(v.size(), 0);

Change the last for loop to :
for (int i = 0; i < v.size(); i++) {
printf("%d ", v[i]);
}

You're clearing your vector, removing all elements and then you seem to be trying to loop through it's first 25 elements, even though it's empty.
The reason you're throwing std_out_of_range is because you're trying to access elements where they don't exist.
You should pretty much never loop through something through an already set number of times if you can't ensure that the vector in question won't have that many elements.
If you absolutely have to loop through your vector a set number of times, at least ensure that your vector will have that many elements first.
if (v.size() >= 25)
{
for (int i = 0; i <= 25; i++)
{
printf("%d ", v[i]);
}
}
In this case your vector will most definitely not have 25 elements since you cleared your vector prior to the loop, but it's much more safe.

Related

How to erase or change element while iterating over vector in C++?

I was in the middle of creating a simple sieve of Erathostenes function when I stumbled upon one obstacle. In to order to accomplish the highest efficiency in this task I wanted to use only a vector. Here is the current code:
vector<int> sieveOfErathostenes(int N) {
vector <int> result(N, 1);
for(int i = 2; i < sqrt(N); i++)
if(result[i] == 1)
for(int j = 2*i; j < N; j += i)
result.at(j) = 0;
// :c
return result;
}
This vector returns 1 and 0 in the proper position but I can't figure out how to implement both erasing or changing an element's value in a single loop. When I use an iterator to erase an element as in erase set element while iterating/// I can't access the vector to change its value, and when I use a standard for loop to access the element I can't remove it. I have tried going from the end of the vector and counting non zero elements and giving some offset when erasing but no success.
TL DR: What I can't figure out is:
for(int i = 0; i < N; i++)
{
if(result[i] == 0) {
//remove at position i
} else {
result.at(i) = i;
}
}
Thank you in advance for your time :)
Instead of erasing elements in the middle of the vector, you should write the results from the beginning of the vector and eliminate the unused elements in the end of vector.
int finalSize = 0;
for(int i = 0; i < N; i++)
{
if(result[i] != 0) {
result[finalSize++] = i;
}
}
result.resize(finalSize);
If you still need to remove an element from a std::vector during traversal, keep in mind that erase returns an iterator following the last removed element:
std::vector<int> result = {1,1,1,0,1,1,1};
for(auto it = result.begin(); it != result.end(); )
{
if(*it==0)
it = result.erase(it);
else
it++;
}

How to Compare multiple variables at the same time in the C++?

I'm making Sudoku validater program that checks whether solved sudoku is correct or not, In that program i need to compare multiple variables together to check whether they are equal or not...
I have provided a snippet of code, what i have tried, whether every su[][] has different value or not. I'm not getting expecting result...
I want to make sure that all the values in su[][] are unequal.
How can i achieve the same, what are mistakes in my snippet?
Thanks...
for(int i=0 ; i<9 ;++i){ //for checking a entire row
if(!(su[i][0]!=su[i][1]!=su[i][2]!=su[i][3]!=su[i][4]!=su[i][5]!=su[i][6]!=su[i][7]!=su[i][8])){
system("cls");
cout<<"SUDOKU'S SOLUTION IS INCORRECT!!";
exit(0);
}
}
To check for each column uniqueness like that you would have to compare each element to the other ones in a column.
e.g.:
for (int i = 0; i < 9; ++i) {
for (int j = 0; j < 9; ++j) {
for (int k = j + 1; k < 9; ++k) {
if (su[i][j] == su[i][k]) {
system("cls");
cout << "SUDOKU'S SOLUTION IS INCORRECT!!\n";
exit(0);
}
}
}
}
Since there are only 8 elements per row this cubic solution shouldn't give you much overhead.
If you had a higher number N of elements you could initialize an array of size N with 0 and transverse the column. For the i-th element in the column you add 1 to that elements position in the array. Then transverse the array. If there's a position whose value is different from 1, it means you have a duplicated value in the column.
e.g.:
for (int i = 0; i < N; ++i) {
int arr[N] = {0};
for (int j = 0; j < N; ++j)
++arr[su[i][j] - 1];
for (int i = 0; i < N; ++i) {
if (arr[i] != 1) {
system("cls");
cout << "SUDOKU'S SOLUTION IS INCORRECT!!\n";
exit(0);
}
}
}
This approach is way more faster than the first one for high values of N.
The codes above check the uniqueness for each column, you would still have to check for each row.
PS: I have not tested the codes, it may have a bug, but hope you get the idea.

Intersection of 2 dynamically allocated arrays c++

I am trying to create a function that will find the intersection of two dynamically allocated arrays comparing array 1 to array 2. For any values in array 1 that are not in array 2, those values should be deleted in array 1 so that array 1 now only holds the common values of both arrays (no repeats). I cannot use vectors, hashes, or any other thing outside of my current functions in my class:
here is my code so far:
bool IntSet::contains(int val) const
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val)
return true;
}
return false;
}
this function compares an integer parameter to values currently stored in the array...if a value is in the array it returns true and if else false;
this next function takes in a value and removes that value from the array:
void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val)
for (int j = 0; j < numValues; j++)
set[j] = set[j + 1];
}
numValues--;
}
here's where I've been having problems, this next function is supposed to iterate through one array and compare those values with the values in the other array...if one value from one array is in the other, it should just skip it, but if a value is not in the array calling the function, it should delete that value from the calling array:
void IntSet::removeDifferent(const IntSet &set2)
{
for (int i = 0; i < set2.size(); i++)
{
if (!set2.contains(set[i]))
{
remove(set[i]);
}
}
}
ive tried about 50 different variations on the removeDifferent() function and I just can't seem to figure this one out. Could someone point me in the right direction?
You're iterating i through the indexes of set2, but then you're testing set[i]. Try this:
void IntSet::removeDifferent(const IntSet &set2)
{
for (int i = 0; i < numValues; ) {
if (!set2.contains(set[i])) {
remove(set[i]);
} else {
i++;
}
}
Note that I also removed i++ from the for loop header. This is because when you remove an element, all the following elements are shifted down, so the next element takes its place in the array. If you incremented i, it would skip that element.
You also need to fix remove. It should start its inner loop from i, so it only shifts down the elements after the one being removed, and it should stop at numValues-1, so it doesn't try to access outside the array when it copies set[j+1]. And as an optimization, it can break out of the outer loop once it has found a match (I assume IntSet doesn't allow duplicates, since you only decrement numValues by 1).
void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val) {
for (int j = i; j < numValues - 1; j++) {
set[j] = set[j + 1];
}
break;
}
}
numValues--;
}
Your problem is in your remove() function:
void IntSet::remove(int val)
{
for (int i = 0; i < numValues; i++)
{
if (set[i] == val)
for (int j = 0; j < numValues; j++)
set[j] = set[j + 1];
}
numValues--;
}
You can figure out yourself why this is wrong by using a paper and pencil here. Start with a typical example: let's say you found the value you're looking for in the third element of a five-element array:
if (set[i] == val)
In this example, i would be set to 2, and numValues would be set to five. It doesn't matter what val is. Whatever it is, you found it when i is 2, and numValues is five: you found it in the third element of a five element array. Keep that in mind.
Now, you know that you are now supposed to remove the third element in this five element array. But what do you think will happen next:
for (int j = 0; j < numValues; j++)
set[j] = set[j + 1];
Well, using the aforementioned paper and pencil, if you work it out, the following will happen:
set[1] will be copied to set[0]
set[2] will be copied to set[1]
set[3] will be copied to set[2]
set[4] will be copied to set[3]
set[5] will be copied to set[4]
There are two problems here:
A) There is no set[5]. Recall that this is a five-element array, si you only have set[0] through set[4]
B) You're not supposed to copy everything in array down to one element. You have to copy only the elements after the element you want to remove.
Fix these two problems, and you will probably find that everything will work correctly.

c++ iterate through all neighbor permutations

I have a vector of N objects, and I would like to iterate through all neighbor permutations of this vector. What I call a neighbor permutation is a permutation where only two elements of the original vector would be changed :
if I have a vector with 'a','b','c','d' then :
'b','a','c','d' //is good
'a','c','b','d' //is good
'b','a','d','c' //is not good (2 permutations)
If I use std::next_permutation(myVector.begin(), myVector.end() then I will get all the possible permutations, not only the "neighbor" ones...
Do you have any idea how that could be achieved ?
Initially, I thought I would filter the permutations that have a hamming distance greater than 2.
However, if you really only need to generate all the vectors resulting by swapping one pair, it would be more efficient if you do like this:
for(int i = 0; i < n; i++)
for(int j = i + 1; j < n; j++)
// swap i and j
Depending on whether you need to collect all the results or not, you should make a copy or the vector before the swap, or swap again i and j after you processed the current permutation.
Collect all the results:
std::vector< std::vector<T> > neighbor_permutations;
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
std::vector<T> perm(v);
std::swap(perm[i], perm[j]);
neighbor_permutations.push_back(perm);
}
}
Faster version - do not collect results:
for(int i = 0; i < n; i++) {
for(int j = i + 1; j < n; j++) {
std::swap(v[i], v[j]);
process_permutation(v);
std::swap(v[i], v[j]);
}
}
Perhaps it's a good idea to divide this into two parts:
How to generate the "neighbor permutations"
How to iterate over them
Regarding the first, it's easy to write a function:
std::vector<T> make_neighbor_permutation(
const std::vector<T> &orig, std::size_t i, std::size_t j);
which swaps i and j. I did not understand from your question if there's an additional constraint that j = i + 1, in which case you could drop a parameter.
Armed with this function, you now need an iterator that iterates over all legal combinations of i and j (again, I'm not sure of the interpretation of your question. It might be that there are n - 1 values).
This is very easy to do using boost::iterator_facade. You simply need to define an iterator that takes in the constructor your original iterator, and sets i (and possibly j) to initial values. As it is incremented, it needs to update the index (or indices). The dereference method needs to call the above function.
Another way to get it, just a try.
int main()
{
std::vector<char> vec={'b','a','c','d'};
std::vector<int> vec_in={1,1,0,0};
do{
auto it =std::find(vec_in.begin(),vec_in.end(),1);
if( *(it++) ==1)
{
for(auto &x : vec)
{
std::cout<<x<<" ";
}
std::cout<<"\n";
}
} while(std::next_permutation(vec_in.begin(),vec_in.end()),
std::next_permutation(vec.begin(),vec.end()) );
}

c++ array can't get the right array

I have Array A[9]= {1,2,3,4,5,6,7,8,9} and I need to delete the numbers which are not dividing by 2. The code I tried to do:
int main()
{
int n;
ifstream fd(Cdf);
fd>>n; // read how many numbers are in the file.
int A[n];
for(int i = 0; i < n; i++)
{
fd >> A[i]; //read the numbers from file
}
for(int i = 0; i < n; i ++) // moving the numbers.
{
if(A[i] % 2 !=0)
{
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
}
}
fd.close();
return 0;
}
But I get numbers like 224466888. what I need to do to get 2,4,6,8?
I need to delete numbers in the same array.
First you should use std::vector for dynamic size arrays.
Second, for removing numbers that are even in a vector, you can do :
std::vector<int> inf = {12,0,5,6,8};
auto func = [](int i){return i % 2 != 0;};
inf.erase(std::remove_if(inf.begin(),inf.end(),func), inf.end());
EDIT :
Ok, so you can still do this without std::vectors, but it will be uglier :
#include <algorithm>
int res[] = {2,5,9,8,6,7};
int size = 6;
auto func = [](int i){return i % 2 != 0;};
int new_size = std::remove_if(res,res + size, func) - res;
All the data you want is in [0, new_size[ range, the other part of your array is now garbage.
Your removal loop is indexing with the wrong variable:
for(int j = i; j < n; j++)
{
A[i] = A[i+1];
}
You're using i, which doesn't change in the loop.
Change it to j. You also need to subtract one from the upper limit, as you'd step outside of the array otherwise when accessing A[j + 1].
for(int j = i; j < n - 1; j++)
{
A[j] = A[j + 1];
}
An array can't be used for your purpose. It is allocated on stack and its size can't be changed dynamically (you can't change the size of an array in general, not only when it is allocated on stack).
You could allocate a second array and keep reallocating it with realloc everytime you add a new element but that's not the good way to do it. You are working with C++ so just use a std::vector<int> and your problems will be solved:
std::vector<int> evenArray;
evenArray.reserve(sizeof(A)/sizeof(A[0])/2);
if (number is even) {
evenArray.pushBack(number);
}
Mind that vector stores elements contiguously so this is legal:
int *evenA = &evenArray[0];
For your inner for loop you should be referencing j, not i.
for(int j = i; j < n - 1; j++)
{
A[j] = A[j+1];
}
Otherwise, what's the point of creating j?
Of course, this also means if you read the whole array back you will display all the characters that were shifted (which will just be equal to the last number). So, you should probably keep track of the new length of the array and just iterate to that instead of the end of the array.
EDIT:
In the inner for loop you need to loop to n - 1 otherwise when you have A[j + 1] it will go off the end of the array when you to change it, which may or may not give you a runtime error.