Add initial cpair functionality

This commit is contained in:
Ivaylo Ivanov 2018-12-08 22:34:47 +01:00
parent 98015cb8b5
commit ccfbf9e1ed
5 changed files with 151 additions and 0 deletions

2
.gitignore vendored
View File

@ -6,3 +6,5 @@
!public/*.html
http/client
http/server
mygrep/mygrep
cpair/cpair

View File

@ -3,5 +3,6 @@ This project contains some basic UNIX command line tools I had to do for TU.
Currently the toolset is ther following:
* mygrep - a simplified version of grep
* http - an implementation of HTTP 1.1 client and server
* cpair - a program that searches for the closest pair of points in a set of 2D-points
Feel free to read the descriptions for each tool.

18
cpair/Makefile Normal file
View File

@ -0,0 +1,18 @@
CC = gcc
CFLAGS = -std=c99 -pedantic -Wall -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_SVID_SOURCE -D_POSIX_C_SOURCE=200809L -g -c
TARGET = cpair
all: $(TARGET).c
$(CC) $(CFLAGS) $(TARGET).c
$(CC) $(TARGET).o -o $(TARGET)
install:
cp $(TARGET) /usr/local/bin/$(TARGET)
clean:
$(RM) $(TARGET).o
$(RM) $(TARGET)
$(RM) *.tgz
package:
tar -cvzf mygrep.tgz $(TARGET).c Makefile

32
cpair/README.md Normal file
View File

@ -0,0 +1,32 @@
# cpair
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`.
**Note: The description and the example are from the task I got from TU.**

98
cpair/cpair.c Normal file
View File

@ -0,0 +1,98 @@
/**
* @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>
float get_x_mean(float *points[2], int arr_len);
int main () {
char input[__UINT8_MAX__] = ""; ///< An array to save the input to
float *points[2]; ///< A pointer to a two-valued array to save the points to
int point_num = 0; ///< Save the number of points
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 array
points[point_num][0] = strtof(x, NULL);
points[point_num][1] = strtof(y, NULL);
point_num++; ///< Increase the array 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", points[0][0], points[0][1]);
printf("%f %f\n", points[1][0], points[1][1]);
exit(EXIT_SUCCESS);
}
float x_mean = get_x_mean(points, point_num);
exit(EXIT_SUCCESS);
}
/**
* @brief Function to calculate the mean of the X coordinates from a points array
* @details Loops through the points array, gets the sum of X coordinates and returns the mean
* @param points - a pointer to an array with the points
* point_num - number of points in the array
* @return mean of all X coordinates
*
**/
float get_x_mean(float *points[2], int point_num) {
float x_sum = 0;
for(int i = 0; i< point_num; i++) {
x_sum += points[i][0];
}
return x_sum/point_num;
}