Advertisement
artmexbet

fourth_task

May 8th, 2024
1,021
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.51 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <time.h>
  4. #include <pthread.h>
  5. #include <string.h>
  6. #include <semaphore.h>
  7.  
  8. #define ROWS 4
  9. #define COLS 5
  10.  
  11. struct ThreadResult {
  12.     int count;
  13.     int indexes[6];
  14. };
  15.  
  16. struct TaskQueue {
  17.     struct TaskQueue *next;
  18.     struct ThreadResult result;
  19.     int threadNumber;
  20. };
  21.  
  22. struct ThreadInfo {
  23.     int matrix[ROWS][COLS];
  24.     int deltaX;
  25.     int deltaY;
  26.     int threadNumber;
  27. };
  28.  
  29. void fill_matrix(int array[ROWS][COLS]) {
  30.     srand(time(NULL));
  31.     for (int i = 0; i < ROWS; i++) {
  32.         for (int j = 0; j < COLS; j++) {
  33.             array[i][j] = 1 + rand() % 3;
  34.         }
  35.     }
  36. }
  37.  
  38. void print_matrix(int array[ROWS][COLS]) {
  39.     for (int i = 0; i < ROWS; i++) {
  40.         for (int j = 0; j < COLS; j++) {
  41.             printf("%d ", array[i][j]);
  42.         }
  43.         printf("\n");
  44.     }
  45. }
  46.  
  47. pthread_mutex_t mutex;
  48. struct TaskQueue *head = NULL;
  49. struct TaskQueue *new = NULL;
  50. struct TaskQueue *tail = NULL;
  51.  
  52. sem_t sem;
  53.  
  54. void *get_values(void *info_) {
  55.     sem_wait(&sem);
  56.  
  57.     struct ThreadInfo *info = (struct ThreadInfo *) info_;
  58.     struct ThreadResult *result = (struct ThreadResult *) malloc(sizeof(struct ThreadResult));
  59.     result->count = 0;
  60.     for (int i = 0; i < ROWS; i++) {
  61.         for (int j = 0; j < COLS; j++) {
  62.             int k = 0;
  63.             int lengthOfHorizontal = 0; // Сюда сохраняем длину повторяющихся символов в строке
  64.             while (0 < j + k && j + k < COLS && info->matrix[i][j + k] == info->matrix[i][j]) {
  65.                 lengthOfHorizontal++;
  66.                 int l = 0;
  67.                 int lengthOfVertical = 0; // Сюда сохраняем длину повторяющихся символов в столбце
  68.                 while (0 < i + l && i + l < ROWS && info->matrix[i + l][j + k] == info->matrix[i][j + k]) {
  69.                     lengthOfVertical++;
  70.                     l += info->deltaX;
  71.                 }
  72.                 if (lengthOfHorizontal + lengthOfVertical > result->count) {
  73.                     result->indexes[0] = i;
  74.                     result->indexes[1] = j;
  75.                     result->indexes[2] = i;
  76.                     result->indexes[3] = j + k;
  77.                     if (l != 0) {
  78.                         result->indexes[4] = i + l - 1 * info->deltaX;
  79.                         // Если в l добавлялись элементы, значение в ней будет на единицу больше (или меньше,
  80.                         // в зависимости от deltaX) из-за того, что мы сначала проверяем, а уже затем увеличиваем l
  81.                         // в цикле while выше
  82.                     } else {
  83.                         // Если же l = 0, вычитать ничего не нужно, нужно лишь записать эту же строку в нужный индекс
  84.                         result->indexes[4] = i;
  85.                     }
  86.                     result->indexes[5] = j + k;
  87.                     result->count = lengthOfHorizontal + lengthOfVertical;
  88.                     // Используем мьютекс для записи промежуточного результата в общую очередь
  89.                     // Лочим поток
  90.                     pthread_mutex_lock(&mutex);
  91.                     tail->result = *result;
  92.                     tail->threadNumber = info->threadNumber;
  93.                     // Выделяем место для следующей операции
  94.                     new = (struct TaskQueue *) malloc(sizeof(struct TaskQueue));
  95.                     tail->next = new;
  96.                     // Заменяем последний элемент на текущий
  97.                     tail = new;
  98.                     // Разблокируем поток
  99.                     pthread_mutex_unlock(&mutex);
  100.                 }
  101.                 k += info->deltaY;
  102.             }
  103.         }
  104.     }
  105.     sem_post(&sem);
  106.     return (void *) result;
  107. }
  108.  
  109. void find_g(int matrix[ROWS][COLS], int k) {
  110.     // Инициализация очереди операций и мьютекса
  111.     head = (struct TaskQueue *) malloc(sizeof(struct TaskQueue));
  112.     tail = head;
  113.     pthread_mutex_init(&mutex, NULL);
  114.  
  115.     sem_init(&sem, 1, k);
  116.  
  117.     int maxCount = 0;
  118.     int coords[] = {0, 0, 0, 0, 0, 0};
  119.     struct ThreadInfo rightUpper, leftUpper, leftLower, rightLower;
  120.     struct ThreadResult *rightUpperResult, *leftUpperResult, *leftLowerResult, *rightLowerResult;
  121.     memcpy(rightUpper.matrix, matrix, ROWS * COLS * sizeof(int));
  122.     memcpy(leftUpper.matrix, matrix, ROWS * COLS * sizeof(int));
  123.     memcpy(leftLower.matrix, matrix, ROWS * COLS * sizeof(int));
  124.     memcpy(rightLower.matrix, matrix, ROWS * COLS * sizeof(int));
  125.     rightUpper.deltaX = 1;
  126.     rightUpper.deltaY = -1;
  127.     rightUpper.threadNumber = 1;
  128.  
  129.     leftUpper.deltaX = -1;
  130.     leftUpper.deltaY = -1;
  131.     leftUpper.threadNumber = 2;
  132.  
  133.     leftLower.deltaX = -1;
  134.     leftLower.deltaY = 1;
  135.     leftLower.threadNumber = 3;
  136.  
  137.     rightLower.deltaX = 1;
  138.     rightLower.deltaY = 1;
  139.     rightLower.threadNumber = 4;
  140.  
  141.     pthread_t thread1, thread2, thread3, thread4;
  142.     // По сути, каждый отдельный поток считает лучший результат для своего угла.
  143.     // После этого основной поток (эта функция) собирает данные воедино и выводит результат
  144.     pthread_create(&thread1, NULL, &get_values, &rightUpper);
  145.     pthread_create(&thread2, NULL, &get_values, &leftUpper);
  146.     pthread_create(&thread3, NULL, &get_values, &leftLower);
  147.     pthread_create(&thread4, NULL, &get_values, &rightLower);
  148.     pthread_join(thread1, (void **) &rightUpperResult);
  149.     pthread_join(thread2, (void **) &leftUpperResult);
  150.     pthread_join(thread3, (void **) &leftLowerResult);
  151.     pthread_join(thread4, (void **) &rightLowerResult);
  152.     if (rightUpperResult->count > maxCount) {
  153.         maxCount = rightUpperResult->count;
  154.         memcpy(coords, rightUpperResult->indexes, sizeof(rightUpperResult->indexes));
  155.     }
  156.     if (leftUpperResult->count > maxCount) {
  157.         maxCount = leftUpperResult->count;
  158.         memcpy(coords, leftUpperResult->indexes, sizeof(leftUpperResult->indexes));
  159.     }
  160.     if (leftLowerResult->count > maxCount) {
  161.         maxCount = leftLowerResult->count;
  162.         memcpy(coords, leftLowerResult->indexes, sizeof(leftLowerResult->indexes));
  163.     }
  164.     if (rightLowerResult->count > maxCount) {
  165.         maxCount = rightLowerResult->count;
  166.         memcpy(coords, rightLowerResult->indexes, sizeof(rightLowerResult->indexes));
  167.     }
  168.     for (int i = 0; i < 6; i++) {
  169.         printf("%d ", coords[i]);
  170.     }
  171.     printf("\nTask queue:\n");
  172.     struct TaskQueue *current = head;
  173.     while (current->next != NULL) {
  174.         printf("Thread %d: ", current->threadNumber);
  175.         for (int i = 0; i < 6; i++) {
  176.             printf("%d ", current->result.indexes[i]);
  177.         }
  178.         printf("\n");
  179.         current = current->next;
  180.     }
  181. }
  182.  
  183. int main() {
  184. //    printf("Hello, World!\n");
  185.     printf("Insert a k number: ");
  186.     int k;
  187.     scanf_s("%d", &k);
  188.     int arr[ROWS][COLS] = {{0, 2, 0, 2, 0},
  189.                            {0, 1, 1, 1, 0},
  190.                            {2, 0, 2, 1, 1},
  191.                            {0, 2, 0, 1, 1}};
  192. //    fill_matrix(arr);
  193.     print_matrix(arr);
  194.     find_g(arr, k);
  195.     return 0;
  196. }
  197.  
Advertisement
Comments
  • artmexbet
    11 days
    # text 0.66 KB | 0 0
    1. Здесь добавляются обычные семафоры. По факту работает это так: есть интовая переменная, равная числу k на старте. Каждый запущенный поток пытается уменьшить её на 1. Если в этой переменной (которая и есть семафор) оказывается 0, то поток сидит и ждёт, пока там не появится что-то большее нуля. Как только появляется, он опять уменьшает на 1 и выполняется сам, а остальные ждут.
Add Comment
Please, Sign In to add comment
Advertisement