简体   繁体   中英

C++ counting how many times data in array changes changed directions?

My program is suppose to count how many times the data in my array changed from increase to decrease or vice versa. For example: {1,2,3,4,3,4} changes twice as the first four elements are increasing then decrease o 3 (causing one change) and then increase back to four causing a second change. The idea in my code was that every time greater or decrease changed to false it would count when it happened but I cannot get it to work. Any help is greatly appreciated as I am really struggling with this!

unsigned count = 0;
bool greater = true;
bool decrease = true;
for (unsigned i = 0; i < elements; i++){
    if (a[i + 1] > a[i]){
        greater = true;
    }
    else
        greater = false;
    count++;
}
for (unsigned i = 0; i < elements; i++){
    if (a[i + 1] < a[i]){
        decrease = true;
    }
    else
        decrease = false;
    count++;
}
        return count;

Your logic is wrong

you may do something like

enum class EDirection { none, decreasing, increasing};

std::size_t count_direction_changes(const std::vector<int>& v)
{
    std::size_t res = 0;
    EDirection direction = EDirection::none;

    for (std::size_t i = 1; i != v.size(); ++i) {
        const int diff = v[i] - v[i - 1];
        switch (direction)
        {
            case EDirection::none: {
                if (diff == 0) {
                    break;
                }
                direction = (diff > 0) ? EDirection::increasing : EDirection::decreasing;
                break;
            }
            case EDirection::increasing: {
                if (diff < 0) {
                    ++res;
                    direction = EDirection::decreasing;
                }
                break;
            }
            case EDirection::decreasing: {
                if (diff > 0) {
                    ++res;
                    direction = EDirection::increasing;
                }
                break;
            }
        }
    }
    return res;
}

Demo

You must change your loops. First of all you should stop the loop at size-1. Because you are comparing with next element and you can go out of bounds if your for is running until elements instead of elements-1.

Furthermore, you have a logic issue. If you are using a boolean variable as flag, you should check if it's true or not before increasing your counter. And in case you increments your counter you must reset that flag. Something similar to down loop should work. Maybe there is some little mistake because I don't have anythin to test it now. But it should be something similar to this.

for (unsigned i = 0; i < elements-1; i++){
    if (a[i + 1] > a[i]){
        greater = true;
    }
    else{
        greater = false;
    }
    if(greater){
        count++;
        greater = false;
    }
 }

This is a lot like Jarod42's, but seeing as I've already coded it will throw it out there. BTW, I use the slightly awkward v[n] < v[n - 1] so it's only necessary to implement operator< to apply the algo to a user-defined type (ie not operator> as well).

#include <iostream>
#include <vector>

template <typename T>
size_t changes(const std::vector<T>& v)
{
    if (v.size() <= 2) return 0;
    size_t count = 0;
    enum { Increasing, Decreasing, Flat } last;
    last = v[0] < v[1] ? Increasing : v[1] < v[0] ? Decreasing : Flat;
    for (size_t i = 2; i < v.size(); ++i)
        if (v[i - 1] < v[i])
        {
            if (last == Decreasing) ++count;
            last = Increasing;
        }
        else if (v[i] < v[i - 1])
        {
            if (last == Increasing) ++count;
            last = Decreasing;
        }
    return count;
}

int main()
{
    std::cout << changes<int>({ 1, 3, 5, 4, 6 }) << '\n';
    std::cout << changes<int>({ 3, 3, 5, 4, 6 }) << '\n';
    std::cout << changes<int>({ 4, 3, 5, 4, 2, 2, 1 }) << '\n';
}

See it run here .

Here is another approach, similar to Tony's and Jarod's:

#include <vector>
#include <cassert>
#include <iostream>

size_t countTrendChanges(const std::vector<int>& a) {
  if (a.size() < 3)
    return 0;

  int trend = 0;
  size_t count = 0;
  for (size_t i = 1; i != a.size(); ++i) {
    int new_trend = (a[i-1] < a[i]) - (a[i] < a[i-1]);
    if (new_trend == 0)
      continue;
    if (trend != 0 && new_trend != trend)
      count++;
    trend = new_trend;
  }
  return count;
}

int main() {
 assert(countTrendChanges({}) == 0); 
 assert(countTrendChanges({1}) == 0); 
 assert(countTrendChanges({3,2,1}) == 0); 
 assert(countTrendChanges({1,2,3}) == 0); 
 assert(countTrendChanges({1,2,2,3}) == 0); 
 assert(countTrendChanges({3,2,1,2,3}) == 1); 
 assert(countTrendChanges({1,2,3,2}) == 1); 
 assert(countTrendChanges({2,1,1,2}) == 1); 
 assert(countTrendChanges({1,2,2,1}) == 1); 
 assert(countTrendChanges({1,2,3,4,3,4}) == 2); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM