SeePlusPlus
SeePlusPlus

Reputation: 167

Change Certain Value When I Detect Change in Vector

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

Answers (4)

Johannes
Johannes

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 &current : 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

Aykhan Hagverdili
Aykhan Hagverdili

Reputation: 29965

Here's how I'd generalize this problem:

  1. Pass it to a function by reference
  2. Check if the vector is empty, if it is, throw an exception
  3. Have a 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

Jonathan Mee
Jonathan Mee

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;
});

Live Example

Upvotes: 0

463035818_is_not_an_ai
463035818_is_not_an_ai

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

Related Questions