cpair.c 4.44 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
/**
 * @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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
41 42 43
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
44

45 46 47 48 49
/// Node struct for linked list
typedef struct node {
    float points[2];
    struct node * next;
} node_t;
50

51 52 53 54
float get_x_mean(node_t * head);
float get_distance(float x1, float x2, float y1, float y2);

int main(void) {
55 56
    char input[__UINT8_MAX__] = ""; ///< An array to save the input to
    int point_num = 0; ///< Save the number of points
57 58 59 60 61 62
    node_t * head = NULL;
    pid_t child_a, child_b;

    head = malloc(sizeof(node_t));

    node_t * current = head;
63 64 65 66 67 68 69

    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) {
70 71 72 73 74 75
            /// 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
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
        } 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) {
91 92
        printf("%f %f\n", head -> points[0], head -> points[1]);
        printf("%f %f\n", head -> next -> points[0], head -> next -> points[1]);
93 94 95
        exit(EXIT_SUCCESS);
    }

96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    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);
127 128 129 130 131

    exit(EXIT_SUCCESS);
}

/**
132 133 134
 * @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
135 136 137
 * @return mean of all X coordinates
 *
 **/
138 139
float get_x_mean(node_t * head) {
    node_t * current = head;
140
    float x_sum = 0;
141 142 143 144 145
    int i = 0;
    while(current -> next != NULL) {
        x_sum += current -> points[0];
        current = current -> next;
        i++;
146
    }
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162

    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));
}