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.