#c
Вопрос:
Ниже приведен код, который я использовал для определения списка порядка чисел (увеличение, уменьшение или неупорядоченный). Или есть какой-либо другой более простой математический способ определить, что список чисел неупорядочен, вместо использования 3 переменных?
Редактировать: 1. В списке может быть дублированный номер (так что я тоже должен иметь сравнение для равного состояния. Спасибо тем, кто указывает на это).
#include <stdio.h>
int main()
{
int num, counter, a, b, c, pattern, unordered_flag;
printf("How many number u want to enter? ");
scanf("%d", amp;num);
counter = 0; b = 0; c = 0;
while(counter < num){
printf("Enter number [%d] : ",counter 1);
scanf("%d", amp;a);
printf("a=%d b=%d c=%d pattern=%dn",a,b,c,pattern); //I used this to check the value of a,b,c and pattern
if(a>b>c){
pattern = 99; //i use 99 to represent increasing order
}
else if(a<b<c){
pattern = 11; //i use 11 to represent decreasing order
}
else{
pattern = 55; //i use 55 to represent unordered order
unordered_flag = 404;
}
c = b;
b = a;
counter = counter 1;
}
if (unordered_flag == 404){
printf("nThe pattern is : Unordered");
}
else if(pattern == 99){
printf("nThe pattern is : Increasing");
}
else if(pattern == 11)
printf("nThe pattern is : Decreasing");
return 0;
}
Комментарии:
1.
if(a>b>c)
не делает то, что вы думаете. Вам нужноif(a>b amp;amp; b>c)
2. Вам просто нужно сравнить первые два числа, чтобы увидеть, увеличиваются они или уменьшаются. Затем сравните каждое оставшееся число с предыдущим, чтобы увидеть, находятся ли они в том же порядке, что и первые два. Как только заказ изменится, вы можете сообщить, что он неупорядочен.
3. вам нужно проверить 4 состояния, а не только три. Четвертое : все равны.
4. @Barmarесли все равны, будет трудно назвать это «неупорядоченным»
5. Это принесло бы большую пользу от
enum
использования вместо магических чисел — вот для чего оно существует. Это можно рассматривать как простой конечный автомат.
Ответ №1:
Это и есть концепция монотонности. В конечном сильно упорядоченном списке вы могли бы использовать конечный автомат.
С помощью (1): переменной для хранения 8 состояний (практически может быть enum
указателем функции or) и (2): памяти последнего элемента, можно полностью определить в режиме онлайн следующее состояние. Расстояние в три перехода — это минимум, который требуется для покрытия вершин.
* Редактировать: более слабую версию этого можно сделать, свернув состояния, выделенные синим цветом.
Например, этот (очень неполный) конечный автомат может быть таким, как это можно было бы сделать с enum
помощью . Это предпочтительнее, чем использовать целочисленные магические значения для удобства чтения и отладки.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
/* X-Macro; just lazy. */
#define STATES X(EMPTY), X(ONE), X(STRICT_INCREASE), X(STRICT_DECREASE),
X(EQUAL), X(INCREASE), X(DECREASE), X(UNORDERED)
int main(int argc, const char **argv) {
struct {
#define X(x) x
enum { STATES } state;
#undef X
int prev;
} sm = { EMPTY, 0 };
#define X(x) #x
static char *names[] = { STATES };
#undef X
int success = EXIT_FAILURE;
(void)argc; /* Unused; `argv` is null-terminated. */
errno = 0; /* `strtol` on POSIX-compliant systems gives more info. */
while(*( argv)) {
/* Read a parameter from the command line. */
char *end;
int num;
long temp = strtol(argv[0], amp;end, 0);
if(errno) goto catch;
if(temp < INT_MIN || temp > INT_MAX)
{ errno = ERANGE; goto catch; }
if(*end != '')
{ errno = EILSEQ; goto catch; }
num = (int)temp;
/* Plug the parameter into the state machine. */
switch(sm.state) {
case EMPTY:
sm.state = ONE; break;
case ONE:
if(sm.prev < num) sm.state = STRICT_INCREASE;
else if(num < sm.prev) sm.state = STRICT_DECREASE;
else sm.state = EQUAL;
break;
case STRICT_INCREASE: /**** TODO! ****/
case STRICT_DECREASE:
case EQUAL:
case INCREASE:
case DECREASE:
sm.state = UNORDERED; break;
case UNORDERED:
break;
}
sm.prev = num;
}
printf("This is %s.n", names[sm.state]);
{ success = EXIT_SUCCESS; goto finally; }
catch:
perror("list-of-ints");
finally:
return success;
}
Комментарии:
1. Интересно! Решение OP (с использованием нескольких переменных с сумасшедшими «значениями флага», такими как «99» и «11»)… это просто неправильно. Вы правы: одна «переменная состояния», которая является «перечислением», — это абсолютно правильный путь. Но нужен ли нам полноценный FSM .. или просто простой цикл «while ()» — это решать оператору.