Skip to content

Commit 7dc53c6

Browse files
2Clutchrzuckerm
andauthored
Add Convex Hull in C (#3958)
--------- Co-authored-by: rzuckerm <[email protected]>
1 parent 0a2cd32 commit 7dc53c6

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

archive/c/c/convex-hull.c

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <string.h>
4+
#include <stdbool.h>
5+
#include <ctype.h>
6+
7+
typedef struct {
8+
int x;
9+
int y;
10+
} Point;
11+
12+
void printUsageAndExit() {
13+
printf("Usage: please provide at least 3 x and y coordinates as separate lists (e.g. \"100, 440, 210\")\n");
14+
exit(1);
15+
}
16+
17+
int compare(const void *p1, const void *p2) {
18+
Point *point1 = (Point *)p1;
19+
Point *point2 = (Point *)p2;
20+
21+
if (point1->x != point2->x) {
22+
return point1->x - point2->x;
23+
}
24+
return point1->y - point2->y;
25+
}
26+
27+
int orientation(Point p, Point q, Point r) {
28+
int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y);
29+
return (val == 0) ? 0 : (val > 0) ? 1 : 2;
30+
}
31+
32+
void convexHull(Point points[], int n) {
33+
Point hull[n];
34+
int hullCount = 0;
35+
36+
qsort(points, n, sizeof(Point), compare);
37+
38+
int l = 0;
39+
for (int i = 1; i < n; i++)
40+
if (points[i].x < points[l].x)
41+
l = i;
42+
43+
int p = l, q;
44+
do {
45+
hull[hullCount++] = points[p];
46+
q = (p + 1) % n;
47+
48+
for (int i = 0; i < n; i++) {
49+
if (orientation(points[p], points[i], points[q]) == 2) {
50+
q = i;
51+
}
52+
}
53+
54+
p = q;
55+
} while (p != l);
56+
57+
for (int i = 0; i < hullCount; i++) {
58+
printf("(%d, %d)\n", hull[i].x, hull[i].y);
59+
}
60+
}
61+
62+
// Function to check if a string is a valid number
63+
bool isInteger(const char *s) {
64+
char *end;
65+
strtol(s, &end, 10); // Convert string to long
66+
return (*end == '\0' || *end == '\n'); // Check if the entire string was valid
67+
}
68+
69+
// Function to trim whitespace from a string
70+
char* trimWhitespace(char *str) {
71+
// Trim leading whitespace
72+
while (isspace((unsigned char)*str)) str++;
73+
// Trim trailing whitespace
74+
char *end = str + strlen(str) - 1;
75+
while (end > str && isspace((unsigned char)*end)) end--;
76+
*(end + 1) = '\0'; // Null terminate after the last non-space character
77+
return str;
78+
}
79+
80+
// Function to parse input string and populate the array
81+
int parseInput(const char *input, int **arr, int *size) {
82+
char *token;
83+
int capacity = 10; // Initial capacity
84+
*arr = malloc(capacity * sizeof(int));
85+
if (*arr == NULL) {
86+
return false;
87+
}
88+
89+
// Tokenize the input string based on commas
90+
char *inputCopy = strdup(input);
91+
if (inputCopy == NULL) {
92+
free(*arr);
93+
*arr = NULL;
94+
return false;
95+
}
96+
97+
token = strtok(inputCopy, ",");
98+
*size = 0;
99+
while (token) {
100+
trimWhitespace(token); // Trim whitespace around token
101+
if (!isInteger(token)) {
102+
free(*arr);
103+
free(inputCopy);
104+
*arr = NULL;
105+
return false; // Exit if a number is invalid
106+
}
107+
108+
if (*size >= capacity) {
109+
capacity *= 2;
110+
*arr = realloc(*arr, capacity * sizeof(int));
111+
if (*arr == NULL) {
112+
free(inputCopy);
113+
return false;
114+
}
115+
}
116+
(*arr)[(*size)++] = atoi(token);
117+
token = strtok(NULL, ",");
118+
}
119+
120+
// Resize the array to the actual size
121+
*arr = realloc(*arr, *size * sizeof(int));
122+
free(inputCopy); // Free the input copy
123+
if (*arr == NULL) {
124+
return false;
125+
}
126+
127+
return true; // Successful parsing
128+
}
129+
130+
void parseCoordinates(char *inputX, char *inputY) {
131+
int *xCoords = NULL;
132+
int *yCoords = NULL;
133+
int xSize = 0;
134+
int ySize = 0;
135+
if (!parseInput(inputX, &xCoords, &xSize) ||
136+
!parseInput(inputY, &yCoords, &ySize) ||
137+
xSize != ySize ||
138+
xSize < 3) {
139+
if (xCoords != NULL) {
140+
free(xCoords);
141+
}
142+
143+
if (yCoords != NULL) {
144+
free(yCoords);
145+
}
146+
147+
printUsageAndExit();
148+
}
149+
150+
int count = xSize;
151+
Point *points = malloc(sizeof(Point) * count);
152+
if (points == NULL) {
153+
free(xCoords);
154+
free(yCoords);
155+
printUsageAndExit();
156+
}
157+
158+
for (int i = 0; i < count; i++) {
159+
points[i].x = xCoords[i];
160+
points[i].y = yCoords[i];
161+
}
162+
163+
free(xCoords);
164+
free(yCoords);
165+
166+
convexHull(points, count);
167+
free(points);
168+
}
169+
170+
int main(int argc, char *argv[]) {
171+
if (argc != 3) {
172+
printUsageAndExit();
173+
}
174+
175+
char *inputX = argv[1];
176+
char *inputY = argv[2];
177+
178+
if (strlen(inputX) == 0 || strlen(inputY) == 0) {
179+
printUsageAndExit();
180+
}
181+
182+
parseCoordinates(inputX, inputY);
183+
return 0;
184+
}

0 commit comments

Comments
 (0)