Few comments:
- I think it is better to structure the code a bit so that it's more manageable, e.g. separate the program's main control from the functions to detect ascending, descending, ascending_then_descending, etc.
- It seems to be easier in my opinion to check ascending, descending, etc using string/char *, rather than using math operation (by leveraging the '0' - '9' character as ASCII).
Below sample will only provide the functionality of checking ascending, descending, etc. Please note that the definition in the following code is using left-to-right
as sequence (as it normally will). Therefore for your case of right-to-left
rule, the string will be reversed
before being processed.
The good thing about using string is that it is also possible to switch the logic of ascending or descending just by reversing the string. Not sure if you have strict rule allowing only to use integer for processing.
Sample output:
N: 1234, F: 0, Return value: 0, Expected: 0
N: 4321, F: 0, Return value: 1, Expected: 1
N: 1234, F: 1, Return value: 1, Expected: 1
N: 4321, F: 1, Return value: 0, Expected: 0
N: 12341, F: 2, Return value: 1, Expected: 1
N: 412341, F: 2, Return value: 0, Expected: 0
N: 96589, F: 2, Return value: 0, Expected: 0
N: 96589, F: 3, Return value: 1, Expected: 1
N: 12341, F: 3, Return value: 0, Expected: 0
Code:
#include <stdio.h>
#include <string.h>
int is_ascending(char *str, int currentIdx, int prevChar);
int is_descending(char *str, int currentIdx, int prevChar);
int is_ascending_then_descending(char *str, int currentIdx, int prevChar, char whichMode);
int is_descending_then_ascending(char *str, int currentIdx, int prevChar, char whichMode);
//===================== Helper Function ======================
void inplace_reverse(char *str);
char* my_itoa(int val, int base);
int main() {
int RetVal=-1, Expected = -1;
int N=0, F=0;
//Ascending
N = 1234, F=0, Expected = 0;
char *input1 = my_itoa(N, 10);
inplace_reverse(input1);
RetVal = is_ascending(input1, 0, 0);
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
N = 4321, F=0, Expected = 1;
char *input2 = my_itoa(N, 10);
inplace_reverse(input2);
RetVal = is_ascending(input2, 0, 0);
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
//Descending
N = 1234, F=1, Expected = 1;
char *input3 = my_itoa(N, 10);
inplace_reverse(input3);
RetVal = is_descending(input3, 0, 0);
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
N = 4321, F=1, Expected = 0;
char *input4 = my_itoa(N, 10);
inplace_reverse(input4);
RetVal = is_descending(input4, 0, 0);
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
//Ascending & then Descending
N = 12341, F=2, Expected = 1;
char *input5 = my_itoa(N, 10);
inplace_reverse(input5);
RetVal = is_ascending_then_descending(input5, 0, 0, 'a');
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
N = 412341, F=2, Expected = 0;
char *input6 = my_itoa(N, 10);
inplace_reverse(input6);
RetVal = is_ascending_then_descending(input6, 0, 0, 'a');
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
N = 96589, F=2, Expected = 0;
char *input7 = my_itoa(N, 10);
inplace_reverse(input7);
RetVal = is_ascending_then_descending(input7, 0, 0, 'a');
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
//Descending & then Ascending
N = 96589, F=3, Expected = 1;
char *input8 = my_itoa(N, 10);
inplace_reverse(input8);
RetVal = is_descending_then_ascending(input8, 0, 999, 'd');
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
N = 12341, F=3, Expected = 0;
char *input9 = my_itoa(N, 10);
inplace_reverse(input9);
RetVal = is_descending_then_ascending(input9, 0, 999, 'd');
printf("N: %d, F: %d, Return value: %d, Expected: %d\n", N, F, RetVal, Expected);
return 0;
}
// ========================= Main Functionality ==========================
//Return 1 if str is Ascending from left to right; otherwise return 0
int is_ascending(char *str, int currentIdx, int prevChar) {
char current = str[currentIdx];
if (current == '\0') {
return 1;
} else {
if (current > prevChar) {
return is_ascending(str, currentIdx+1, current);
} else {
return 0;
} //end else
} //
}
//Return 1 if str is Descending from left to right; otherwise return 0.
//Re-use the 'is_asscending' function by reversing the string first
int is_descending(char *str, int currentIdx, int prevChar) {
inplace_reverse(str);
return is_ascending(str, currentIdx, prevChar);
}
//Return 1 if str is Ascending and then Descending (from left to right); otherwise return 0.
int is_ascending_then_descending(char *str, int currentIdx, int prevChar, char whichMode) {
char current = str[currentIdx];
if (current == '\0') {
return 1;
} else {
if (current > prevChar) {
if (whichMode == 'a') {
return is_ascending_then_descending(str, currentIdx+1, current, whichMode);
} else { //mode is already in Descending, but current > prevChar
return 0;
} //end else
} else { //current <= prevChar
if (whichMode == 'a') {
return is_ascending_then_descending(str, currentIdx+1, current, 'd'); //switch to descending mode
} else { //mode is already in Descending, current <= prevChar
if (current < prevChar) {
return is_ascending_then_descending(str, currentIdx+1, current, 'd');
} else { //current == prevChar
return 0;
}
} //end else
} //end else
} //
}
//Return 1 if str is Descending and then Ascending (from left to right); otherwise return 0.
int is_descending_then_ascending(char *str, int currentIdx, int prevChar, char whichMode) {
char current = str[currentIdx];
if (current == '\0') {
return 1;
} else {
if (current < prevChar) {
if (whichMode == 'd') {
return is_descending_then_ascending(str, currentIdx+1, current, whichMode);
} else { //mode is already in Ascending, but current < prevChar
return 0;
} //end else
} else { //current >= prevChar
if (whichMode == 'd') {
return is_descending_then_ascending(str, currentIdx+1, current, 'a'); //switch to ascending mode
} else { //mode is already in Ascending, current <= prevChar
if (current > prevChar) {
return is_descending_then_ascending(str, currentIdx+1, current, 'a');
} else { //current == prevChar
return 0;
}
} //end else
} //end else
} //
}
//============================= Helper Function ==============================
//reverse the given null-terminated string in place
//From: https://stackoverflow.com/questions/784417/reversing-a-string-in-c
void inplace_reverse(char *str) {
if (str) {
char *end = str + strlen(str) - 1;
// swap the values in the two given variables
// XXX: fails when a and b refer to same memory location
# define XOR_SWAP(a,b) do\
{\
a ^= b;\
b ^= a;\
a ^= b;\
} while (0)
// walk inwards from both ends of the string,
// swapping until we get to the middle
while (str < end)
{
XOR_SWAP(*str, *end);
str++;
end--;
}
# undef XOR_SWAP
}
}
char* my_itoa(int val, int base) {
static char buf[32] = {0};
int i = 30;
for(; val && i ; --i, val /= base)
buf[i] = "0123456789abcdef"[val % base];
return &buf[i+1];
}