Home > Software engineering >  Check if range of values is ascending, descending, or non-monotonous
Check if range of values is ascending, descending, or non-monotonous

Time:11-07

I am looking for a hint to find out strictly the condition for non monotonous.

The string of numbers ends with the value 0, where 0 is not part of the heights (only marks the end of the string).

Specify whether the range of heights is ascending, descending, or non-monotonous.

Input             Output
---------------------------
1 2 5 5 10 11 0   ascending
16 7 3 0          descending
1 2 2 1 0         non-monotonous

Solving as much as possible with while and if and int.

Restrictions and clarifications:

  • 0 is not part of the string of heights, only marks the end of the string
  • heights are numbers between 0 and 10,000
  • for simplicity if all numbers are equal or there is no value before 0, the string is considered non-monotonous

How I tried to solve it :

int main(){

    int   b ,  a   , ascending = 0  , counter = 0 , descending = 0 ;
    
       cin >> a;
     while( a != 0 ){
        cin >> b;
           counter;
    if( a && b != 0 ){

        if( a <  b ){
           ascending;
        }
        else if(a > b ){
           descending;
        }
        }
           a = b;
    }
     --counter;
     if(ascending == counter  ){
         cout << "\n ascending";
     }
     else if ( descending > 2 ){
         cout << " non-monotonous ";
     }

     if(descending == counter){
         cout << "\n descending ";
     }
     else if ( ascending > 2 ){
        cout << " non-monotonous ";
     }
}

CodePudding user response:

I would recommend you to make two bool variables and name it ascending and descending and assign true to them. And also always keep the current number that you have and the last number.

Then you can execute the while loop how you do it

If you get this situation:

last_number>current_number

then you just assign false for ascending variable

and if you have last_number<current_number

then conversely

After you loop is over, the answer will be in this variables.

CodePudding user response:

here is how i would solve it but don't worry, i will explain how I reasoned when I wrote the code. this solution is to be considered useful for school purposes only since using c standards utilities you can check the sequence with a near two lines long check (other users have responded with much more fast, clean and sane methods than this)

int main()
{
    bool descending = true;
    bool ascending = true;
    bool equals = true;
    
    int num = -1;
    int last_num = -1;
    
    std::cin >> num;
    last_num = num;
    
    while( num != 0 ){
        if(ascending)
            ascending = last_num <= num;
        if(descending)
            descending = last_num >= num;
        if(equals)
            equals = last_num == num;
        
        last_num = num;
        std::cin >> num;
    }
    
    if(equals)
        std::cout << "non-monotonous";
    else if(descending)
        std::cout << "descending";
    else if(ascending)
        std::cout << "ascending";
    else
        std::cout << "non-monotonous";
    return 0;
}

In this case you can't store the whole sequence and exam it at the end. So the unique way you got to check what condition (ascending, descending, non-monotonous) is respected is to store what conditions are still valid with the previous integers and to check them with the new one.

To do this i stored (is)descending (is)ascending and (is)equals in three (initially true) booleans. Every time i get a new input i check what of them is still true, once verified what conditions are still true i can check them one by one (only the ones that are still true) and verify if the new input break one of them.

When the while is finished (and i got the last 0 number which is discarded) the last phase is to check which conditions are still true, giving priority to (is)equals since it can be true without invalidate the other two conditions.

descending and ascending are self-excluding so only one of them can be true, so no matter what of these two i check after the first (equals).

In case i got three false condition the sequence is surely non-monotonous.


EDIT (Thanks to @Pete Becker for the hints)

We can improve the code making it shorter and cleaner with two more things.

-The first point is the conditions check about descending and ascending. For brevity we could make it like this :

    ascending &= last_num <= num;
    descending &= last_num >= num;

The bitwise operator &= apply the AND operation on the bits of ascending and descending variables. The unique way for these variables to keep true as value is to pass to &= operator only true right values. In short, if only once the right value is false, the bool value of the variable will be false for the rest of the loop.

-The second point is about equals variable. It is not strictly necessary since we can know if all values are equal by checking if both descending and ascending are true.

CodePudding user response:

If you have a range of integers*, you can use std::is_sorted to write the following function

std::string monotonous(std::vector<int> const & v)
{
    if (v.empty() or 
        std::equal(std::begin(v), std::end(v) - 1, std::begin(v)   1))
       return "non-monotonous";
    if (std::ranges::is_sorted(v))
        return "ascending";
    else 
    if (std::ranges::is_sorted(v, std::greater{}))
        return "descending";
    else
       return "non-monotonous";
}

Here's a demo.

If you don't have C 20, the std::ranges::is_sorted can be replaced with std::is_sorted, and the iterators into the range have to be specified explicitly, e.g. std::is_sorted(std::begin(v), std::end(v), std::greater{}).


*if the values are being read in from standard input, add them to a vector<int> (except for the last 0), and then call the function.

  • Related