I have a vector of vectors.
How would I check to see if all elements in one of the columns are the same?
I`ve tried to check it with this nested for loop but I'm getting an out of range error.
void move_bee(vector< vector<insect> > &insects_on_board){
for(int i = 0; i < 10; i++){
for(int j = 0; j < insects_on_board.at(i).size(); j++){
for(int k = insects_on_board.at(i).size(); k > 0; k--){
if(insects_on_board.at(i).at(j) == "B" &&
insects_on_board.at(i).at(k) == "B"){
insects_on_board.at(i-1).push_back(bee());
insects_on_board.at(i).erase(insects_on_board.at(i).begin() + j);
}
}
}
}
}
I have read about the:
if (equal(myVector.begin() + 1, myVector.end(), myVector.begin()) )
method but it would not compile for me, I am assuming its because it's a vector of vectors.
The initial value of k is off the end: use
for(auto k=v.size(); k--;)
to loop backwards.
The use of at(i-1) must also be wrong, since i starts at 0.
Unless your vector is sorted, checking just two elements can’t tell you if they’re all equal.
Finally, even if you can’t use a range-for (because of index use like i-1 and ...+j), do bind a reference to the element you’re working on, at least at the outer level. The readability improvement is significant.
Related
The Diffk II Problem is :
Given an array A of integers and another non negative integer k, find if there exists 2 indices i and j such that A[i] - A[j] = k, i != j
The code I found online is :
if (a.size() < 2 || k < 0) return 0;
set<int> s;
//for(int el : a)
// s.insert(el);
for(int i=0;i<a.size();i++)
{
int diff1 = a[i]-k;
int diff2 = k+a[i];
if(s.find(diff1)!=s.end())
return 1;
if(s.find(diff2)!=s.end())
return 1;
s.insert(a[i]);
}
return 0;
Why am not getting the correct output if uncomment the 2 lines in the beginning and comment the insert statement inside the for loop ?
And why are we using a set? When we use a set, we ignore the duplicates present in the vector.
Can't we use a map? So that we do not lose any element in case the input vector contains duplicate values?
If you uncomment the 2 lines
//for(int el : a)
// s.insert(el);
It means all elements will be added at the beginning.
k is non negative, so it may become zero.
Therefore, the function will give ignore the i != j condition and give false-positive when k is zero (searching for A[i] = A[j]).
When inerting inside the loop, the indice of elements in s are granteed to be less than i.
That is because the i != j condition won't ignored in this case.
Assuming that, you don't have to use the indice otherwise, so using map to hold indice is not required.
For my class, we are using two compilers, xcode and codeboard, where codeboard is the more rigorous of the two and has a list of preset asserts to test your code. In my code for function a, I have nested loops, where I want i to always be one ahead of k. It works fine in xcode, but gives me a segmentation fault on codeboard.
for (int k = 0; k <= n-2; k++) {
for (int i = k+1; i <= n-1; i++) {
if (array[k] == array[i])
What's strange is if I use k++ or ++k instead of k+1, it won't result in a segmentation fault, but my code won't pass all the asserts. I thought they were supposed to be the same thing?
What's even more strange is if I use k+1 in function b, it doesn't result in an error in codeboard.
for (int k = 0; k <= n-1; k++) {
for (int i = k+1; i <= n-1; i++) {
if (array[k] > array[i])
Basically, what is happening here?
Edit: So, what I'm getting from everyone is that when I use i = k+1 in the inner loop, it increases the k value in the outer loop. Like, if k=1, i=2, then when it goes back to the outer loop, k=3. If that's the case, how would I get i from staying ahead of k?
Edit: Please ignore the k++ and k+1 part of my question, that was not really my main issue, just a side thing that kind of confused me, but I get the difference now. I'd delete that part from my post, but I'm pretty sure that's not allowed. My main question is how to keep my i value 1 greater than my k value.
In the following code, the goal is if any of the array values are the same, it should cout true at some point. In regards to reproducible results:
string a[3] = {"aaa", "bbbb", "cccc"};
int n = 3;
for (int k = 0; k <= n-2; k++) {
int b = 0;
for (int i = k+1; i <= n-1; i++) {
if (a[k] == a[i])
b++;
}
if (b != 0) {
cout << "true" << endl;
break;
}
else
cout << "false" << endl;
}
No, they're not the same:
k + 1
Returns the value of k plus one, but does not change the value of k itself.
++k
Adds 1 to k and returns the new value (pre-increment).
k++
Also adds 1 to k but returns the previous value of k (post-increment).
k++ and ++k both increase k by one, changing the value of k.
k+1 does not.
Your segmentation fault comes from the fact that you are increasing k every time your initial for-loop is evaluated but also every time your second for loop is initialized. This means that you're reading further than your array at the end of your loop.
k++ and k+1 are not the same.
If you use k++ instead of k+1 inside the loop in the code you have shown, you are actually performing two increments on the variable k, which is usually not what you want in the control variable of a loop.
K+1 does not alter the value of k.
k++ increments k after using its value.
++k increments k before using its value.
So basically what is happening is that every time you start the inner loop, k gets incremented. But in the last round of the external loop, when k is equal to n-1, you perform another increment, which sets k to n, and this is most certainly not what you wanted.
Suppose I have a vector that contains n strings, where the strings can be length 5...n. Each string must be compared with each string character by character. If there is a mismatch, the score is increased by one. If there is a match, the score does not increase. Then I will store the resulting scores in a matrix.
I have implemented this in the following way:
for (auto i = 0u; i < vector.size(); ++i)
{
// vector.size() x vector.size() matrix
std::string first = vector[i]; //horrible naming convention
for (auto j = 0u; j < vector.size(); ++j)
{
std::string next = vector[j];
int score = 0;
for (auto k = 0u; k < sizeOfStrings; ++k)
{
if(first[k] == second[k])
{
score += 0;
}
else
{
score += 1;
}
}
//store score into matrix
}
}
I am not happy with this solution because it is O(n^3). So I have been trying to think of other ways to make this more efficient. I have thought about writing another function that would replace the innards of our j for loop, however, that would still be O(n^3) since the function would still need a k loop.
I have also thought about a queue, since I only care about string[0] compared to string[1] to string[n]. String[1] compared to string[2] to string[n]. String[2] compared to string[3] to string[n], etc. So my solutions have unnecessary computations since each string is comparing to every other string. The problem with this, is I am not really sure how to build my matrix out of this.
I have finally, looked into the std template library, however std::mismatch doesn't seem to be what I am looking for, or std::find. What other ideas do you guys have?
I don't think you can easily get away from O(n^3) comparisons, but you can easily implement the change you talk about. Since the comparisons only need to be done one way (i.e. comparing string[1] to string[2] is the same as comparing string[2] to string[1]), as you point out, you don't need to iterate through the entire array each time and can change the start value of your inner loop to be the current index of your outer loop:
for (auto i = 0u; i < vector.size(); ++i) {
// vector.size() x vector.size() matrix
std::string first = vector[i]; //horrible naming convention
for (auto j = i; j < vector.size(); ++j) {
To store it in a matrix, setup your i x j matrix, initialize it to all zeroes and simply store each score in M[i][j]
for (auto k = 0u; k < sizeOfStrings; ++k) {
if (first[k] != second[k]) {
M[i][j]++;
}
}
If you have n strings each of length m, then no matter what (even with your queue idea), you have to do at least (n-1)+(n-2)+...+(1)=n(n-1)/2 string comparisons, so you'll have to do (n(n-1)/2)*m char comparisons. So no matter what, your algorithm is going to be O(mn^2).
General comment:
You don't have to compare the same strings with each other. And what is more important you starting from the begining each time in second loop while you already computed those diffs, so change the second loop to start from i+1.
By doing so your complexity will decrease as you won't check string that you already checked or are the same.
Improvement
Sort vector and remove duplicated entries, then instead wasting computation for checking the same strings you will only check those that are different.
The other answers that say this is at least O(mn^2) or O(n^3) are incorrect. This can be done in O(mn) time where m is string size and n is number of strings.
For simplicity we'll start with the assumption that all characters are ascii.
You have a data structure:
int counts[m][255]
where counts[x][y] is the number of strings that have ascii character y at index x in the string.
Now, if you did not restrict to ascii, then you would need to use a std::map
map counts[m]
But it works the same way, at index m in counts you have a map in which each entry in the map y,z tells you how many strings z use character y at index m. You would also want to choose a map with constant time lookups and constant time insertions to match the complexity.
Going back to ascii and the array
int counts[m][255] // start by initializing this array to all zeros
First initialize the data structure:
m is size of strings,
vec is a std::vector with the strings
for (int i = 0; i < vec.size(); i++) {
std::string str = vec[i];
for(int j = 0; j < m; j++) {
counts[j][str[j]]++;
}
}
Now that you have this structure, you can calculate the scores easily:
for (int i = 0; i < vec.size(); i++) {
std::string str = vec[i];
int score = 0;
for(int j = 0; j < m; j++) {
score += counts[j][str[j]] - 1; //subtracting 1 gives how many other strings have that same char at that index
}
std::cout << "string \"" << str << "\" has score " << score;
}
As you can see by this code, this is O(m * n)
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()) );
}
The following function takes three word objects and checks each word's letter coordinates (in a table) against each other. The idea is to get combinations of three words from a list that don't have intersecting letter coordinates. However when you have over 600000 possible combinations this becomes very time consuming.
bool lettersIntersect(word one, word two, word three)
{
for(int i = 0; i < one.getLength(); i++)
for(int j = 0; j < two.getLength(); j++)
if(one.getLetterPosition(i).x == two.getLetterPosition(j).x && one.getLetterPosition(i).y == two.getLetterPosition(j).y)
return true;
for(int i = 0; i < two.getLength(); i++)
for(int j = 0; j < three.getLength(); j++)
if(two.getLetterPosition(i).x == three.getLetterPosition(j).x && two.getLetterPosition(i).y == three.getLetterPosition(j).y)
return true;
for(int i = 0; i < three.getLength(); i++)
for(int j = 0; j < one.getLength(); j++)
if(three.getLetterPosition(i).x == one.getLetterPosition(j).x && three.getLetterPosition(i).y == one.getLetterPosition(j).y)
return true;
return false;
}
Is there a more efficient way of doing this?
I can just give you 1 hint which striked me instantly. Don't blame me if its misleading. You can just try once at your end and see the performance.
Create map (use stl) for each word objects i.e. map_one, map_two, and map_three
Add co-ordinate value as key for each letter of a given word object to its respective map.
Then check using these maps whether there is an intersection.
Check if map in C++ contains all the keys from another map
The only thing I see possible to optimize is avoiding double checks:
for(int i = 0; i < one.getLength(); i++)
for(int j = i+1; j < two.getLength(); j++)
if(one.getLetterPosition(i).x == two.getLetterPosition(j).x && one.getLetterPosition(i).y == two.getLetterPosition(j).y)
return true;
The second for loop was changed from j = 0, to j = i+1, which makes you do the checks in half the time.
Checking between two coordinates points is a n^2 (n-square) problem, which means that the time required to do the checks is proportional to square the number of elements you can check. I thikn there's no other way to optimize this other than avoiding double checks, like I explained.
Of course, in addition to passing by references, like was suggested to you already.
On this homework problem or other learning exercise, you are intended to use a method you have been taught previously that rearranges data to make searching faster. Having rearranged the data, you should be able to find a way to scan it efficiently to find duplicates.