Advertisement
sp1d3o

izp2

Dec 4th, 2022 (edited)
404
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 11.25 KB | None | 0 0
  1. /**
  2.  * Pavel  Valenta
  3.  * xvalen33
  4.  * 2.12.2022
  5.  * IZP Project 2 - Data Structures
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #include <math.h> // sqrtf
  12. #include <limits.h> // INT_MAX
  13. #include <string.h>
  14. #include <errno.h>
  15.  
  16. /*****************************************************************
  17.  * Ladici makra. Vypnout jejich efekt lze definici makra
  18.  * NDEBUG, napr.:
  19.  *   a) pri prekladu argumentem prekladaci -DNDEBUG
  20.  *   b) v souboru (na radek pred #include <assert.h>
  21.  *      #define NDEBUG
  22.  */
  23. #ifdef NDEBUG
  24. #define debug(s)
  25. #define dfmt(s, ...)
  26. #define dint(i)
  27. #define dfloat(f)
  28. #else
  29.  
  30. // vypise ladici retezec
  31. #define debug(s) printf("- %s\n", s)
  32.  
  33. // vypise formatovany ladici vystup - pouziti podobne jako printf
  34. #define dfmt(s, ...) printf(" - "__FILE__":%u: "s"\n",__LINE__,__VA_ARGS__)
  35.  
  36. // vypise ladici informaci o promenne - pouziti dint(identifikator_promenne)
  37. #define dint(i) printf(" - " __FILE__ ":%u: " #i " = %d\n", __LINE__, i)
  38.  
  39. // vypise ladici informaci o promenne typu float - pouziti
  40. // dfloat(identifikator_promenne)
  41. #define dfloat(f) printf(" - " __FILE__ ":%u: " #f " = %g\n", __LINE__, f)
  42.  
  43. #endif
  44.  
  45. /*****************************************************************
  46.  * Deklarace potrebnych datovych typu:
  47.  *
  48.  * TYTO DEKLARACE NEMENTE
  49.  *
  50.  *   struct objt_t - struktura objektu: identifikator a souradnice
  51.  *   struct cluster_t - shluk objektu:
  52.  *      pocet objektu ve shluku,
  53.  *      kapacita shluku (pocet objektu, pro ktere je rezervovano
  54.  *          misto v poli),
  55.  *      ukazatel na pole shluku.
  56.  */
  57.  
  58. struct obj_t {
  59.     int id;
  60.     float x;
  61.     float y;
  62. };
  63.  
  64. struct cluster_t {
  65.     int size;
  66.     int capacity;
  67.     struct obj_t *obj;
  68. };
  69.  
  70. /*****************************************************************
  71.  * Deklarace potrebnych funkci.
  72.  *
  73.  * PROTOTYPY FUNKCI NEMENTE
  74.  *
  75.  * IMPLEMENTUJTE POUZE FUNKCE NA MISTECH OZNACENYCH 'TODO'
  76.  *
  77.  */
  78.  
  79.  
  80. void init_cluster(struct cluster_t *c, int cap)
  81. {
  82.     assert(c != NULL);
  83.     assert(cap >= 0);
  84.  
  85.     if (cap == 0)
  86.         c->obj = NULL;
  87.     else
  88.     {
  89.         size_t size = sizeof(struct obj_t) * cap;
  90.         c->obj = malloc(size);
  91.         assert(c->obj != NULL);
  92.     }
  93.  
  94.     c->capacity = cap;
  95.     c->size = 0;
  96. }
  97.  
  98.  
  99. void clear_cluster(struct cluster_t *c)
  100. {
  101.     assert(c != NULL);
  102.  
  103.     if (c->obj != NULL)
  104.         free(c->obj);
  105.  
  106.     c->obj = NULL;
  107.     c->capacity = 0;
  108.     c->size = 0;
  109. }
  110.  
  111. /// Chunk of cluster objects. Value recommended for reallocation.
  112. const int CLUSTER_CHUNK = 10;
  113.  
  114. struct cluster_t *resize_cluster(struct cluster_t *c, int new_cap)
  115. {
  116.  
  117.     assert(c);
  118.     assert(c->capacity >= 0);
  119.     assert(new_cap >= 0);
  120.  
  121.     if (c->capacity >= new_cap)
  122.         return c;
  123.  
  124.     size_t size = sizeof(struct obj_t) * new_cap;
  125.  
  126.     void *arr = realloc(c->obj, size);
  127.     if (arr == NULL)
  128.         return NULL;
  129.  
  130.     c->obj = arr;
  131.     c->capacity = new_cap;
  132.     return c;
  133. }
  134.  
  135.  
  136. void append_cluster(struct cluster_t *c, struct obj_t obj)
  137. {
  138.     assert(c != NULL);
  139.     //expand cluster, if there is not enough space
  140.     if (c->size+1 > c->capacity)
  141.     {
  142.         resize_cluster(c, c->capacity > 0 ? c->capacity * 2 : 1);
  143.     }
  144.     c->obj[c->size] = obj;
  145.     c->size += 1;
  146. }
  147.  
  148.  
  149. void sort_cluster(struct cluster_t *c);
  150.  
  151.  
  152. void merge_clusters(struct cluster_t *c1, struct cluster_t *c2)
  153. {
  154.     assert(c1 != NULL);
  155.     assert(c2 != NULL);
  156.  
  157.     for (int i = 0; i < c2->size; i++)
  158.     {
  159.         append_cluster(c1, c2->obj[i]);
  160.     }
  161.     sort_cluster(c1);
  162. }
  163.  
  164. int remove_cluster(struct cluster_t *carr, int narr, int idx)
  165. {
  166.     assert(idx < narr);
  167.     assert(narr > 0);
  168.  
  169.     //first remove cluster on index idx
  170.     clear_cluster(&(carr[idx]));
  171.     //than move other items in array
  172.     for (int i = idx; i < narr-1; i++)
  173.     {
  174.         carr[i] = carr[i+1];
  175.     }
  176.  
  177.     //return array_size - 1
  178.     return narr-1;
  179. }
  180.  
  181. float obj_distance(struct obj_t *o1, struct obj_t *o2)
  182. {
  183.     assert(o1 != NULL);
  184.     assert(o2 != NULL);
  185.  
  186.     return sqrtf((o1->x - o2->x)*(o1->x - o2->x) + (o1->y - o2->y)*(o1->y - o2->y));
  187. }
  188.  
  189.  
  190. float cluster_distance(struct cluster_t *c1, struct cluster_t *c2)
  191. {
  192.     assert(c1 != NULL);
  193.     assert(c1->size > 0);
  194.     assert(c2 != NULL);
  195.     assert(c2->size > 0);
  196.  
  197.     //first set minimum value to compare with
  198.     float min = 10000;
  199.     //two for cycles, for two clusters
  200.     for (int i = 0; i < c1->size; i++) {
  201.         for (int j = 0; j < c2->size; j++)
  202.         {
  203.             //calculate distance and save it to tmp
  204.             float tmp = (obj_distance(&(c1->obj[i]), &(c2->obj[j])));
  205.             //compare with min value, if tmp is smaller, replace it
  206.             if (tmp < min)
  207.                 min = tmp;
  208.         }
  209.     }
  210.     //return final minimum
  211.     return min;
  212. }
  213.  
  214.  
  215. void find_neighbours(struct cluster_t *carr, int narr, int *c1, int *c2)
  216. {
  217.     assert(narr > 0);
  218.     assert(carr != NULL);
  219.  
  220.     //if there is only one value, no need to calculate
  221.     if (narr == 1)
  222.     {
  223.         *c1 = 0;
  224.         *c2 = 0;
  225.     }
  226.  
  227.     //if there are two items, no need to calculate
  228.     else if (narr == 2)
  229.     {
  230.         *c1 = 0;
  231.         *c2 = 1;
  232.     }
  233.     else
  234.     {
  235.         float min = 9999;
  236.         //same as previous function
  237.         for (int i = 0; i < narr; i++)
  238.         {
  239.             for (int j = i+1; j < narr; j++)
  240.             {
  241.                 float tmp = (cluster_distance(&(carr[i]), &(carr[j])));
  242.                 if (tmp < min)
  243.                 {
  244.                     //when found, set indexes
  245.                     min = tmp;
  246.                     *c1 = i;
  247.                     *c2 = j;
  248.                 }
  249.             }
  250.         }
  251.     }
  252. }
  253.  
  254. static int obj_sort_compar(const void *a, const void *b)
  255. {
  256.     const struct obj_t *o1 = a;
  257.     const struct obj_t *o2 = b;
  258.     if (o1->id < o2->id) return -1;
  259.     if (o1->id > o2->id) return 1;
  260.     return 0;
  261. }
  262.  
  263.  
  264. void sort_cluster(struct cluster_t *c)
  265. {
  266.     qsort(c->obj, c->size, sizeof(struct obj_t), &obj_sort_compar);
  267. }
  268.  
  269.  
  270. void print_cluster(struct cluster_t *c)
  271. {
  272.     for (int i = 0; i < c->size; i++)
  273.     {
  274.         if (i) putchar(' ');
  275.         printf("%d[%g,%g]", c->obj[i].id, c->obj[i].x, c->obj[i].y);
  276.     }
  277.     putchar('\n');
  278. }
  279.  
  280.  
  281. int load_clusters(char *filename, struct cluster_t **arr)
  282. {
  283.     assert(arr != NULL);
  284.  
  285.     FILE * file;
  286.  
  287.     //First, open the file and check if it is OK
  288.  
  289.  
  290.     if ((file = fopen(filename, "r")) == NULL)
  291.     {
  292.         fprintf(stderr, "File could not be opened\n");
  293.         //if opening failed, we need to close it and clean memory
  294.         *arr = NULL;
  295.         fclose(file);
  296.         return -1;
  297.     }
  298.  
  299.     // First line - count=<number>
  300.  
  301.     //two buffers with purpose to store particular lines
  302.     char buff1[7];
  303.     char buff2[101];
  304.  
  305.     int var;
  306.     //Number of clusters which will be needed to load
  307.     int counter = 0;
  308.     //number of controlled line of code
  309.     int line_variable = 1;
  310.     //fgets function used to read each line with specific amount of bytes
  311.     if (fgets(buff1, 7, file) == NULL)
  312.     {
  313.         fprintf(stderr, "Error during file reading\n");
  314.         *arr = NULL;
  315.         return -1;
  316.     }
  317.     if (strcmp(buff1, "count=\0") != 0)
  318.     {
  319.         fprintf(stderr, "First line has to contain: count=<number>\n");
  320.         *arr = NULL;
  321.         return -1;
  322.     }
  323.     if (fgets(buff2, 101, file) == NULL)
  324.     {
  325.         fprintf(stderr, "Error during file reading - missing value\n");
  326.         *arr = NULL;
  327.         return -1;
  328.     }
  329.     var = sscanf(buff2, "%d", &counter);
  330.  
  331.     if (var < 1 || var == EOF )
  332.     {
  333.         fprintf(stderr, "Error during file reading - wrong value\n");
  334.         *arr = NULL;
  335.         return -1;
  336.     }
  337.     if (counter <= 0)
  338.     {
  339.         fprintf(stderr, "NUmber of object must be greater than zero\n");
  340.         *arr = NULL;
  341.         return -1;
  342.     }
  343.  
  344.     //contiunue with reading lines
  345.     for (int i = 0; i < counter; i++)
  346.     {
  347.         line_variable++;
  348.  
  349.         char buff3[304];
  350.         int helper_var;
  351.  
  352.         int new_id;
  353.         int axe_x;
  354.         int axe_y;
  355.         if (fgets(buff3, 304, file) == NULL)
  356.         {
  357.             fprintf(stderr, "Error reading file\n");
  358.             *arr = NULL;
  359.             return -1;
  360.         }
  361.         helper_var = sscanf(buff3, "%d %d %d", &new_id, &axe_x, &axe_y);
  362.         if (helper_var < 3 ||helper_var == EOF )
  363.         {
  364.             fprintf(stderr, "Error reading line\n");
  365.             *arr = NULL;
  366.             return -1;
  367.         }
  368.         if (axe_x < 0 || axe_x > 1000 || axe_y < 0 || axe_y > 1000)
  369.         {
  370.             fprintf(stderr, "Coordinates values out of range\n");
  371.             *arr = NULL;
  372.             return -1;
  373.         }
  374.     }
  375.  
  376.     //continue reading file
  377.  
  378.     rewind(file);
  379.     struct cluster_t *clusters = malloc(sizeof(struct cluster_t)*counter);
  380.  
  381.     while (1)
  382.     {
  383.         int help = fgetc(file);
  384.         if (help == '\n')
  385.             break;
  386.     }
  387.     // reading another objects
  388.     for (int i = 0; i < counter; i++)
  389.     {
  390.         char buffer[108];
  391.         int new_id;
  392.         int axe_x;
  393.         int axe_y;
  394.  
  395.         fgets(buffer, 108, file);
  396.         sscanf(buffer, "%d %d %d", &new_id, &axe_x, &axe_y);
  397.         struct obj_t new_obj;
  398.         new_obj.id = new_id;
  399.         new_obj.x = axe_x;
  400.         new_obj.y = axe_y;
  401.  
  402.         struct cluster_t c;
  403.         init_cluster(&c, 1);
  404.         append_cluster(&c, new_obj);
  405.         clusters[i] = c;
  406.     }
  407.     fclose(file);
  408.     *arr = &clusters[0];
  409.     return counter;
  410. }
  411.  
  412.  
  413. void print_clusters(struct cluster_t *carr, int narr)
  414. {
  415.     printf("Clusters:\n");
  416.     for (int i = 0; i < narr; i++)
  417.     {
  418.         printf("cluster %d: ", i);
  419.         print_cluster(&carr[i]);
  420.     }
  421. }
  422.  
  423. int main(int argc, char *argv[])
  424. {
  425.     //cluster aray
  426.     struct cluster_t *clusters;
  427.  
  428.     //number of clusters
  429.     int cluster_count;
  430.     //number of wanted clusters
  431.     int cluster_req; //
  432.  
  433.     //processing and checking arguments
  434.     if (argc < 2)
  435.     {
  436.         fprintf(stderr, "Missing arguments\n");
  437.         return 1;
  438.     }
  439.     if (argc > 2)
  440.     {
  441.         long int test_var;
  442.         //strtol function is safer than atoi - due to overflow risks
  443.         test_var = strtol(argv[2], NULL, 10);
  444.         if (errno == ERANGE || test_var > INT_MAX || test_var <= 0 )
  445.         {
  446.             fprintf(stderr, "Invalid cluster_count or out of range\n");
  447.             return 1;
  448.         }
  449.         cluster_req = (int)test_var;
  450.     }
  451.     else
  452.     {
  453.         cluster_req = 1;
  454.     }
  455.  
  456.     //using load_cluster function to read and load from file
  457.  
  458.     cluster_count = load_clusters(argv[1], &clusters);
  459.     // if cluster_count is lower than  zero, something failed
  460.     if (cluster_count < 0)
  461.         return 1;
  462.     if (cluster_count < cluster_req)
  463.     {
  464.         fprintf(stderr, "Not enough read objects\n");
  465.         return 1;
  466.     }
  467.  
  468.  
  469.     //repeat until this condition won´t match
  470.     while(cluster_count != cluster_req)
  471.     {
  472.         int first;
  473.         int second;
  474.         find_neighbours(clusters, cluster_count, &first, &second);
  475.         merge_clusters(&(clusters[first]), &(clusters[second]));
  476.         cluster_count = remove_cluster(clusters, cluster_count, second);
  477.     }
  478.  
  479.  
  480.     //print clusters
  481.     print_clusters(clusters, cluster_count);
  482.     //and free memory
  483.     free(clusters);
  484.  
  485.     return 0;
  486. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement