Reputation: 167
So, I have the following vector:
vector<int> vec = {2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9};
I have a value offset which starts at 0:
int offset = 0;
I want to go through the array and change the offset value accordingly. For example, if we started at the beginning (at the first 2), the I want
offset = 0;
And then, when it arrives at the second 2, I want
offset = -16;
But ONCE I see that the array value is no longer 2 (it changes), I want offset to reset to 0 (and then if it sees the next 3, it will become offset = offset - 16
).
I want to keep subtracting 16 from my offset value as long as the value in the vector doesn't change while I iterate over it. But once I detect a change, I want to reset offset.
What is the best way to do this?
Upvotes: 0
Views: 787
Reputation: 6707
#include <vector>
#include <iostream>
int Test(const std::vector<int> &vec)
{
int offset = 0;
int previous = vec.size() > 0 ? vec[0] : 0;
for (auto ¤t : vec)
{
if (previous == current) offset -= 16;
else offset = 0;
previous = current;
}
return offset;
}
int main(int, char*[])
{
std::cout << "None " << Test({}) << "\n";
std::cout << "One " << Test({ 9 }) << "\n";
std::cout << "Two Equal " << Test({ 9, 9 }) << "\n";
std::cout << "Two Differnt " << Test({ 9, 8 }) << "\n";
std::cout << "Many " << Test({ 2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9 }) << "\n";
return 0;
}
To find the best solution for you you should consider testing whatever solution you create so that you know it has the behavior you want. The output of this snippet can be inspected and you can check the individual tests with a debugger. Consider using a testing framework to preserve tests for the future.
Upvotes: 1
Reputation: 29965
Here's how I'd generalize this problem:
for
loop, and declare offset
outside it, so you can manually reset offset
whenever you want.Example implementation:
#include <iostream>
#include <vector>
#include <stdexcept>
void gen_offset(const std::vector<int>& vec) {
if (vec.empty()) {
throw std::runtime_error("Vector is empty");
}
int offset = 0;
int curr_val = vec[0];
for (size_t i = 1; i != vec.size(); ++i) {
if (vec[i] == curr_val) {
offset -= 16;
}
else {
std::cout << curr_val << " => " << offset << std::endl;
offset = 0;
curr_val = vec[i];
}
}
}
int main() {
std::vector<int> vec = {2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4,
5, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9};
gen_offset(vec);
return 0;
}
Output:
2 => -16
3 => -32
4 => -96
5 => 0
6 => -16
8 => -176
Upvotes: 0
Reputation: 38919
It's unclear what you want to do with offset
or where you want to obtain it. But if you're just looking for a way to output it on a per element basis you could hack adjacent_find
or similar:
auto offset = 0;
cout << offset << ' ';
adjacent_find(cbegin(vec), cend(vec), [&](const auto lhs, const auto rhs){
if(lhs == rhs) {
offset -= 16;
} else {
offset = 0;
}
cout << offset << ' ';
return false;
});
Upvotes: 0
Reputation: 122298
This is just what you explain in words translated to code:
vector<int> vec = {2, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 6, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9};
int offset = 0;
int current = vec[0];
for (unsigned i = 1; i< vec.size(); ++i) {
if (vec[i] == current) offset -= 16;
else offset = 0;
current = vec[i];
}
Though I dont really understand what this is supposed to be good for, or what you mean with "best way". However, the code was too much for a comment....
Upvotes: 1