/** * @file cpair.c * @author Ivaylo Ivanov 11777707 * @date 08.12.2018 * * @brief Main program module. * * A program that searches for the closest pair of points in a set of 2D-points * * SYNOPSIS * cpair * * EXAMPLE * $ cat 1.txt * 4.0 4.0 * -1.0 1.0 * 1.0 -1.0 * -4.0 -4.0 * $ ./cpair < 1.txt * -1.000000 1.000000 * 1.000000 -1.000000 * * * The program accepts an array of 2D-points as an input from stdin. The input ends at EOF. * * The program does the following: * - No output if the array has one point * - The points if the array has 2 points * - Otherwise, the array is split in 2 parts based on the mean of X and sent to 2 different paralell child processes. The parent watches for the return code of the children and terminates with an error if any of the children exit with anything other than success. * * Algorithm description when there are more than 2 points: * - P1 and P2 are the closest pairs for the first and the second part respectively. * - Go through all of the pairs between the points from the first half with the second half and save the shortest one in P3. * - Compare P1, P2 and P3 and return the shortest one to stdout. * **/ #include #include #include #include #include #include #include /// Node struct for linked list typedef struct node { float points[2]; struct node * next; } node_t; float get_x_mean(node_t * head); float get_distance(float x1, float x2, float y1, float y2); int main(void) { char input[__UINT8_MAX__] = ""; ///< An array to save the input to int point_num = 0; ///< Save the number of points node_t * head = NULL; pid_t child_a, child_b; head = malloc(sizeof(node_t)); node_t * current = head; while(fgets(input, __INT8_MAX__, stdin) != NULL) { ///< Read line by line /// Split the input by whitespace as delimiter char *x = strtok(input, " "); char *y = strtok(NULL, " "); if(x != NULL && y != NULL) { /// Convert to float and save to the list current -> points[0] = strtof(x, NULL); current -> points[1] = strtof(y, NULL); current -> next = malloc(sizeof(node_t)); current = current -> next; point_num++; ///< Increase the list length } else { puts("ERROR: Ill-formed line found"); exit(EXIT_FAILURE); } } if(feof(stdin) == 0) { puts("ERROR: An error interrupted the read"); exit(EXIT_FAILURE); } if(point_num == 1) exit(EXIT_SUCCESS); if(point_num == 2) { printf("%f %f\n", head -> points[0], head -> points[1]); printf("%f %f\n", head -> next -> points[0], head -> next -> points[1]); exit(EXIT_SUCCESS); } float x_mean = get_x_mean(head); child_a = fork(); child_b = fork(); switch(child_a){ case -1: puts("ERROR: Coudn't fork child"); exit(EXIT_FAILURE); case 0: puts("Child"); break; default: break; } switch(child_b){ case -1: puts("ERROR: Coudn't fork child"); exit(EXIT_FAILURE); case 0: puts("Child"); break; default: break; } int status; waitpid(child_a, &status, 0); waitpid(child_b, &status, 0); exit(EXIT_SUCCESS); } /** * @brief Function to calculate the mean of the X coordinates from a points list * @details Loops through the points list, gets the sum of X coordinates and returns the mean * @param head - a pointer to a list with the points * @return mean of all X coordinates * **/ float get_x_mean(node_t * head) { node_t * current = head; float x_sum = 0; int i = 0; while(current -> next != NULL) { x_sum += current -> points[0]; current = current -> next; i++; } return x_sum/i; } /** * @brief Function to calculate the distance between 2 points * @details The function calculates the distance between 2 points * in a Cartesian coordinate system, given their coordinates * @param x1, y1 - pair of coordinates for the first point * x2, y2 - pair of coordinates for the second point * @return distance between the two points * **/ float get_distance(float x1, float x2, float y1, float y2) { return sqrt(pow((x2 - x1), 2) + pow((y2 - y1), 2)); }