diff --git a/analyzers/polynomials/stack/poly_calc.c b/analyzers/polynomials/stack/poly_calc.c new file mode 100644 index 0000000..a0263a9 --- /dev/null +++ b/analyzers/polynomials/stack/poly_calc.c @@ -0,0 +1,162 @@ +#include "poly_calc.h" +#include +#include +#include + +// Возведение полинома в целую степень +Polynomial deg_poly(Polynomial *p, int degree) { + Polynomial result; init_polynomial(&result); + Polynomial temp = copy_poly(p); + for (int i = 1; i < degree; i++) { + Polynomial new_result = mul_polynomials(&temp, p); + free_polynomial(&temp); + temp = new_result; + } + result = temp; + return result; +} + +// Возвращает копию полинома +Polynomial copy_poly(Polynomial *p) { + Polynomial result; init_polynomial(&result); + for (int i = 0; i < p->size; ++i) { + add_term(&result, p->terms[i].coefficient, p->terms[i].exponent); + } + return result; +} + +Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2) { + Polynomial result; init_polynomial(&result); + + for (int i = 0; i < p1->size; ++i) { + for (int j = 0; j < p2->size; ++j) { + Term t1 = p1->terms[i]; + Term t2 = p2->terms[j]; + + // Результат перемножения двух слагаемых + Term res_t; + res_t.coefficient = t1.coefficient * t2.coefficient; + res_t.exponent = t1.exponent + t2.exponent; + + // Прибавление полученного результата (слагаемого) + // к результирующему полиному + add_term_and_poly(&result, res_t); + } + } + + return result; +} + +Polynomial sub_polynomials(Polynomial *p1, Polynomial *p2) { + for (int i = 0; i < p2->size; ++i) { + p2->terms[i].coefficient *= -1; + } + return add_polynomials(p1, p2); +} + +// Cложение полиномов +Polynomial add_polynomials(Polynomial *p1, Polynomial *p2) { + Polynomial result; init_polynomial(&result); + + for (int i = 0; i < p1->size; ++i) { + add_term_and_poly(&result, p1->terms[i]); + } + + for (int i = 0; i < p2->size; ++i) { + add_term_and_poly(&result, p2->terms[i]); + } + + return result; +} + +// Сложение одного слагаемого и полинома +void add_term_and_poly(Polynomial *p, Term term) { + Term* t = exist_incremental(p, term); + if (t) { + t->coefficient += term.coefficient; + } else { + add_term(p, term.coefficient, term.exponent); + } +} + +// Например есть полином x+1 и терм (2,1)=2x, значит в полиноме есть +// incremental (увеличиваемое), т.е. есть к чему прибавить 2x +Term* exist_incremental(Polynomial *p, Term term) { + for (int i = 0; i < p->size; ++i) { + if (p->terms[i].exponent == term.exponent) { + return &p->terms[i]; + } + } + return NULL; +} + +// Инициализация полинома +void init_polynomial(Polynomial *p) { + p->size = 0; + p->capacity = 4; + p->terms = (Term *)malloc(p->capacity * sizeof(Term)); + if (!p->terms) { + perror("Memory allocation failed"); + exit(EXIT_FAILURE); + } +} + +// Добавление слагаемого в полином +void add_term(Polynomial *p, int coeff, int exp) { + // Проверяем, нужно ли расширить массив + if (p->size >= p->capacity) { + p->capacity *= 2; + p->terms = (Term *)realloc(p->terms, p->capacity * sizeof(Term)); + if (!p->terms) { + perror("Memory reallocation failed"); + exit(EXIT_FAILURE); + } + } + + // Добавляем слагаемое + p->terms[p->size].coefficient = coeff; + p->terms[p->size].exponent = exp; + p->size++; +} + +// Сортировка слагаемых в полиноме по убыванию степени +void sort_polynomial(Polynomial *p) { + for (int i = 0; i < p->size - 1; i++) { + for (int j = 0; j < p->size - i - 1; j++) { + if (p->terms[j].exponent < p->terms[j + 1].exponent) { + // Обмен слагаемых + Term temp = p->terms[j]; + p->terms[j] = p->terms[j + 1]; + p->terms[j + 1] = temp; + } + } + } +} + +// Освобождение памяти, занятой полиномом +void free_polynomial(Polynomial *p) { + free(p->terms); + p->terms = NULL; + p->size = 0; + p->capacity = 0; +} + +// Печать полинома +void print_polynomial(Polynomial *p) { + if (p->size == 0) { + printf("0\n"); return; + } + + for (int i = 0; i < p->size; i++) { + // Печать знака + if (p->terms[i].coefficient > 0) { printf("+"); + } else { printf("-"); } + // Печать коэффициента + printf("%d", abs(p->terms[i].coefficient)); + // Печать переменной и степени + if (p->terms[i].exponent > 0) { + printf("x^%d", p->terms[i].exponent); + } + } + printf("\n"); +} \ No newline at end of file diff --git a/analyzers/polynomials/stack/poly_calc.h b/analyzers/polynomials/stack/poly_calc.h new file mode 100644 index 0000000..0b01310 --- /dev/null +++ b/analyzers/polynomials/stack/poly_calc.h @@ -0,0 +1,45 @@ +#ifndef POLY_CALC_H +#define POLY_CALC_H + +// Структура для представления слагаемого +typedef struct { + int coefficient; // коэффициент + int exponent; // степень переменной +} Term; + +// Структура для представления полинома +typedef struct { + Term *terms; // массив слагаемых + int size; // количество слагаемых + int capacity; // вместимость массива +} Polynomial; + +// Инициализация полинома +void init_polynomial(Polynomial *p); +// Добавление слагаемого в полином +void add_term(Polynomial *p, int coeff, int exp); +// Сортировка слагаемых в полиноме по убыванию степени +void sort_polynomial(Polynomial *p); +// Освобождение памяти, занятой полиномом +void free_polynomial(Polynomial *p); +// Копирование полинома +// Polynomial copy_poly(Polynomial *p); +// Печать полинома +void print_polynomial(Polynomial *p); +// Возвращает копию полинома +Polynomial copy_poly(Polynomial *p); +// Например есть полином x+1 и терм (2,1)=2x, значит в полиноме есть +// incremental (увеличиваемое), т.е. есть к чему прибавить 2x +Term* exist_incremental(Polynomial *p, Term term); +// Сложение одного слагаемого и полинома (вспомогательная функция) +void add_term_and_poly(Polynomial *p, Term term); +// Вернет сумму двух полиномов +Polynomial add_polynomials(Polynomial *p1, Polynomial *p2); +// Вычтет p2 из p1 и вернет разность +Polynomial sub_polynomials(Polynomial *p1, Polynomial *p2); +// Перемножит полиномы, вернет результат +Polynomial mul_polynomials(Polynomial *p1, Polynomial *p2); +// Возведение полинома в целую степень +Polynomial deg_poly(Polynomial *p1, int degree); + +#endif \ No newline at end of file diff --git a/analyzers/polynomials/stack/stack.c b/analyzers/polynomials/stack/stack.c deleted file mode 100644 index f27c22a..0000000 --- a/analyzers/polynomials/stack/stack.c +++ /dev/null @@ -1,128 +0,0 @@ -#include "stack.h" -#include -#include -#include - -void initStack(Stack *s) { - s->top = -1; -} - -bool isEmpty(Stack *s) { - return s->top == -1; -} - -bool isFull(Stack *s) { - return s->top == MAX_STACK_SIZE - 1; -} - -bool push(Stack *s, const char *value, char type) { - if (isFull(s)) { - fprintf(stderr, "Stack overflow!\n"); - return false; - } - char *new_str = malloc(strlen(value) + 1); - if (new_str == NULL) { - fprintf(stderr, "Memory allocation failed!\n"); - return false; - } - strcpy(new_str, value); - s->top++; - s->data[s->top].str_ptr = new_str; - s->data[s->top].type = type; - return true; -} - -bool pop(Stack *s, Element *out) { - if (isEmpty(s)) { - fprintf(stderr, "Stack is empty!\n"); - return false; - } - *out = s->data[s->top--]; - return true; -} - -bool peek(Stack *s, Element *out) { - if (isEmpty(s)) { - fprintf(stderr, "Stack is empty!\n"); - return false; - } - *out = s->data[s->top]; - return true; -} - -void clearStack(Stack *s) { - while (s->top >= 0) { - free(s->data[s->top].str_ptr); - s->top--; - } -} - -char* calulate(Element* tokens, int tokens_count) { - #define MAX_ELEMENT_STRING_SIZE 100 - Stack s_operands; - initStack(&s_operands); - for (int i = 0; i < tokens_count; ++i) { - Element token = tokens[i]; - if (token.type == 'n' || token.type == 'v') { - // если число или выражение с переменной - добавляю в стек - push(&s_operands, token.str_ptr, token.type); - } else { - // если оператор - char op = token.str_ptr[0]; - - // беру со стека 2 последних операнда - Element second_operand; pop(&s_operands, &second_operand); - Element first_operand; pop(&s_operands, &first_operand); - - char result[MAX_ELEMENT_STRING_SIZE] = { 0 }; - - if (first_operand.type == 'n' && second_operand.type == 'n') { - // оба операнда - числа => вычисляю значение выражения и его закидываю в стек - int first_num = atoi(first_operand.str_ptr); - int second_num = atoi(second_operand.str_ptr); - - switch (op) { - case '+': { - int result_num = first_num + second_num; - //printf("%i + %i = %i\n", first_num, second_num, result_num); - snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); - push(&s_operands, result, 'n'); - break; - } - case '-': { - int result_num = first_num - second_num; - //printf("%i - %i = %i\n", first_num, second_num, result_num); - snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); - push(&s_operands, result, 'n'); - break; - } - case '*': { - int result_num = first_num * second_num; - //printf("%i * %i = %i\n", first_num, second_num, result_num); - snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num); - push(&s_operands, result, 'n'); - break; - } - } - } else { - // хотя бы один операнд содержит переменную - - snprintf(result, MAX_ELEMENT_STRING_SIZE, "(%s%c%s)", first_operand.str_ptr, op, second_operand.str_ptr); - //printf("%s %c %s = %s\n", first_operand.str_ptr, op, second_operand.str_ptr, result); - push(&s_operands, result, 'v'); // Помечаю как выражение с переменной - } - - free(first_operand.str_ptr); - free(second_operand.str_ptr); - } - } - - if (!isEmpty(&s_operands)) { - Element result; - pop(&s_operands, &result); - //printf("Result: %s\n", result.str_ptr); - return result.str_ptr; - } - - return NULL; -} \ No newline at end of file diff --git a/analyzers/polynomials/stack/stack.h b/analyzers/polynomials/stack/stack.h deleted file mode 100644 index 561cd2d..0000000 --- a/analyzers/polynomials/stack/stack.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef STACK_H -#define STACK_H - -#include -#include - -#define MAX_STACK_SIZE 100 - -// Структура элемента стека -typedef struct { - char *str_ptr; // Указатель на строку - char type; // Тип операнда -} Element; - -// Структура стека -typedef struct { - Element data[MAX_STACK_SIZE]; // Массив элементов - int top; -} Stack; - -// Инициализация стека -void initStack(Stack *s); - -// Проверка на пустоту -bool isEmpty(Stack *s); - -// Проверка на переполнение -bool isFull(Stack *s); - -// Добавление опаранда в стек (push), -// операндом может быть число или выражение с переменной -bool push(Stack *s, const char *value, char type); - -// Извлечение элемента из стека (pop) -bool pop(Stack *s, Element *out); - -// Просмотр верхнего элемента без извлечения (peek) -bool peek(Stack *s, Element *out); - -// Очистка стека (освобождение памяти) -void clearStack(Stack *s); - -// Вычисление выражения -char* calulate(Element* tokens, int tokens_count); - -#endif // STACK_H \ No newline at end of file diff --git a/analyzers/polynomials/stack/stack_test.c b/analyzers/polynomials/stack/stack_test.c deleted file mode 100644 index 5f2ffe0..0000000 --- a/analyzers/polynomials/stack/stack_test.c +++ /dev/null @@ -1,63 +0,0 @@ -// калькулятор на основе обратной польской записи - -// gcc stack_test.c stack.c -o stack_test.exe - -#include "stack.h" -#include -#include -#include - -// Тестирование сценария: -// Токен: 2 -> Стек: [2] -// Токен: 2 -> Стек: [2, 2] -// Токен: 10 -> Стек: [2, 2, 10] -// Токен: 3 -> Стек: [2, 2, 10, 3] -// Токен: - -> Берем 3 и 10: 10-3=7 -> Стек: [2, 2, 7] -// Токен: * -> Берем 7 и 2: 2*7=14 -> Стек: [2, 14] -// Токен: x -> Стек: [2, 14, x] -// Токен: 8 -> Стек: [2, 14, x, 8] -// Токен: - -> Берем 8 и x: x-8 -> Стек: [2, 14, (x-8)] -// Токен: * -> Берем (x-8) и 14: 14*(x-8) -> Стек: [2, (14*(x-8))] -// Токен: + -> Берем (14*(x-8)) и 2: 2+(14*(x-8)) -> Стек: [(2+(14*(x-8)))] -// Ответ: (2+(14*(x-8))) - -// P.S. и еще нескольких - -int main() { - - char* res; - Element tokens[100]; - - tokens[0].str_ptr = "2"; tokens[0].type = 'n'; // number - tokens[1].str_ptr = "2"; tokens[1].type = 'n'; // number - tokens[2].str_ptr = "10"; tokens[2].type = 'n'; // number - tokens[3].str_ptr = "3"; tokens[3].type = 'n'; // number - tokens[4].str_ptr = "-"; tokens[4].type = 'o'; // operator - tokens[5].str_ptr = "*"; tokens[5].type = 'o'; // operator - tokens[6].str_ptr = "x"; tokens[6].type = 'v'; // variable - tokens[7].str_ptr = "8"; tokens[7].type = 'n'; // number - tokens[8].str_ptr = "-"; tokens[8].type = 'o'; // operator - tokens[9].str_ptr = "*"; tokens[9].type = 'o'; // operator - tokens[10].str_ptr = "+"; tokens[10].type = 'o'; // operator - res = calulate(tokens, 11); - printf("Result: %s\n", res); - free(res); - - tokens[0].str_ptr = "2"; tokens[0].type = 'n'; - tokens[1].str_ptr = "2"; tokens[1].type = 'n'; - tokens[2].str_ptr = "+"; tokens[2].type = 'o'; - res = calulate(tokens, 3); - printf("Result: %s\n", res); - free(res); - - tokens[0].str_ptr = "2"; tokens[0].type = 'n'; - tokens[1].str_ptr = "2"; tokens[1].type = 'n'; - tokens[2].str_ptr = "+"; tokens[2].type = 'o'; - tokens[3].str_ptr = "x"; tokens[3].type = 'v'; - tokens[4].str_ptr = "*"; tokens[4].type = 'o'; - res = calulate(tokens, 5); - printf("Result: %s\n", res); - free(res); - - return 0; -} \ No newline at end of file diff --git a/analyzers/polynomials/stack/test_poly_calc.c b/analyzers/polynomials/stack/test_poly_calc.c new file mode 100644 index 0000000..e11761d --- /dev/null +++ b/analyzers/polynomials/stack/test_poly_calc.c @@ -0,0 +1,145 @@ +// gcc test_poly_calc.c poly_calc.c + +#include +#include +#include "poly_calc.h" + +void tests(); +void test1(); +void test2(); +void test3(); +void test4(); +void test5(); + +int main() { + tests(); + return 0; +} + +void test5() { + printf("TEST 5: UINT DEGREE\n"); + // (-6x^4+3x+1)^5 = -7776x^20+19440x^17+6480x^16-19440x^14-12960x^13-2160x^12+9720x^11+9720x^10+3240x^9-2070x^8-3240x^7-1620x^6-117x^5+375x^4+270x^3+90x^2+15x^1+1 + + Polynomial p; + init_polynomial(&p); + add_term(&p, 1, 0); + add_term(&p, -6, 4); + add_term(&p, 3, 1); + Polynomial res = deg_poly(&p, 5); + sort_polynomial(&res); + + printf("EXPECTED:\n-7776x^20+19440x^17+6480x^16-19440x^14-12960x^13-2160x^12+9720x^11+9720x^10+3240x^9-2070x^8-3240x^7-1620x^6-117x^5+375x^4+270x^3+90x^2+15x^1+1\n"); + printf("OUTPUT:\n"); + print_polynomial(&res); + + free_polynomial(&p); + free_polynomial(&res); +} + +void test4() { + printf("TEST 4: MUL\n"); + // (-6x^4+3x+1) * (3x^4+2x^2-10) = -18x^8-12x^6+9x^5+63x^4+6x^3+2x^2-30x^1-10 + + Polynomial p1, p2; + init_polynomial(&p1); + add_term(&p1, 1, 0); + add_term(&p1, -6, 4); + add_term(&p1, 3, 1); + init_polynomial(&p2); + add_term(&p2, -10, 0); + add_term(&p2, 2, 2); + add_term(&p2, 3, 4); + Polynomial res = mul_polynomials(&p1, &p2); + sort_polynomial(&res); + + printf("EXPECTED:\n-18x^8-12x^6+9x^5+63x^4+6x^3+2x^2-30x^1-10\n"); + printf("OUTPUT:\n"); + print_polynomial(&res); + + free_polynomial(&p1); + free_polynomial(&p2); + free_polynomial(&res); + + +} + +void test3() { + printf("TEST 3: SUB\n"); + // (-6x^4+3x+5x+10+1) - (3x^4+2x^2-10) = -9x^4-2x^2+8x^1+21 + Polynomial p1, p2; + init_polynomial(&p1); + add_term(&p1, 1, 0); + add_term(&p1, -6, 4); + add_term(&p1, 3, 1); + add_term(&p1, 5, 1); + add_term(&p1, 10, 0); + init_polynomial(&p2); + add_term(&p2, -10, 0); + add_term(&p2, 2, 2); + add_term(&p2, 3, 4); + Polynomial res = sub_polynomials(&p1, &p2); + sort_polynomial(&res); + + printf("EXPECTED:\n-9x^4-2x^2+8x^1+21\n"); + printf("OUTPUT:\n"); + print_polynomial(&res); + + free_polynomial(&p1); + free_polynomial(&p2); + free_polynomial(&res); +} + +void test2() { + printf("TEST 2: ADD\n"); + // (-6x^4+3x+1) + (3x^4+2x^2-10) = -3x^4+2x^2+3x-9 + Polynomial p1, p2; + init_polynomial(&p1); + add_term(&p1, 1, 0); + add_term(&p1, -6, 4); + add_term(&p1, 3, 1); + init_polynomial(&p2); + add_term(&p2, -10, 0); + add_term(&p2, 2, 2); + add_term(&p2, 3, 4); + Polynomial res = add_polynomials(&p1, &p2); + sort_polynomial(&res); + + printf("EXPECTED:\n-3x^4+2x^2+3x^1-9\n"); + printf("OUTPUT:\n"); + print_polynomial(&res); + + free_polynomial(&p1); + free_polynomial(&p2); + free_polynomial(&res); +} + +void test1() { + printf("TEST 1: INIT\n"); + Polynomial poly1, poly2; + init_polynomial(&poly1); + add_term(&poly1, 3, 2); + add_term(&poly1, 2, 1); + add_term(&poly1, -1, 0); + sort_polynomial(&poly1); + init_polynomial(&poly2); + add_term(&poly2, -2, 3); + add_term(&poly2, 4, 2); + add_term(&poly2, -5, 0); + sort_polynomial(&poly2); + + printf("EXPECTED:\n+3x^2+2x^1-1\n-2x^3+4x^2-5\n"); + printf("OUTPUT:\n"); + print_polynomial(&poly1); + print_polynomial(&poly2); + + free_polynomial(&poly1); + free_polynomial(&poly2); +} + +void tests() { + test1(); printf("\n\n"); + test2(); printf("\n\n"); + test3(); printf("\n\n"); + test4(); printf("\n\n"); + test5(); +} \ No newline at end of file