about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2025-07-06 15:16:03 -0500
committergennyble <gen@nyble.dev>2025-07-06 15:16:03 -0500
commitb1aef90e6d4bc231a057b034a452e748ef59e783 (patch)
tree98960211ff0cd6a7371f1197865ed9b33e12ed3b
downloadsenseless-b1aef90e6d4bc231a057b034a452e748ef59e783.tar.gz
senseless-b1aef90e6d4bc231a057b034a452e748ef59e783.zip
meow
-rw-r--r--.vscode/settings.json3
-rw-r--r--Makefile8
-rw-r--r--readme26
-rw-r--r--senseless.h106
-rw-r--r--test.c50
5 files changed, 193 insertions, 0 deletions
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..b0d0749
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+	"editor.formatOnSave": false
+}
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..1eee1a6
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,8 @@
+CC = gcc
+
+test:
+	$(CC) test.c -o test
+	./test
+
+clean:
+	rm test
\ No newline at end of file
diff --git a/readme b/readme
new file mode 100644
index 0000000..ae04c7f
--- /dev/null
+++ b/readme
@@ -0,0 +1,26 @@
+senseless directions
+----------------------
+
+convert a series of cardinal directions into a measure of degree
+because we all know that NWWWNNNWWN is a sensible way to direct.
+
+#INCLUDE "senseless.h"
+	senseless directions can be used as a single-header library. you'll
+	want the file called senseless.h in the root of the repository. then
+	just include it in your code and you're good.
+
+INTERFACE
+	double senseless_directions(const char *directions, size_t length);
+		takes a string of [NnEeSsWw] characters and produces a
+		measure of degree.
+
+MAKEFILE
+	if you have make installed you can use the following subcommands. if
+	make is not installed, you can look at the Makefile for the commands
+	that are run.
+
+	test
+		compile and run the tests.
+
+	clean
+		remove artifacts created by the makefile
\ No newline at end of file
diff --git a/senseless.h b/senseless.h
new file mode 100644
index 0000000..e84eed4
--- /dev/null
+++ b/senseless.h
@@ -0,0 +1,106 @@
+#ifndef SENSELESS_H
+#define SENSELESS_H
+
+#include <stddef.h> // size_t
+#include <stdio.h>
+
+void _clamp(double lower, double upper, double *value) {
+	if (*value < lower) {
+		*value = lower;
+	} else if (*value > upper) {
+		*value = upper;
+	}
+}
+
+void _wrap(double *degree) {
+	do {
+		if (*degree < 0)
+			*degree += 360;
+		
+		if (*degree >= 360)
+			*degree -= 360;
+	} while (*degree < 0 || *degree >= 360);
+}
+
+void _min(double *value, double lower) {
+	if (*value < lower)
+		*value = lower;
+}
+
+void _max(double *value, double upper) {
+	if (*value > upper)
+		*value = upper;
+}
+
+double senseless_directions(const char *directions, size_t length) {
+	double degrees = 0.0;
+	double factor = 90.0;
+	size_t consumed = 0;
+
+	do {
+		if (length - consumed == 0)
+			return degrees;
+
+		char current = directions[consumed];
+		if (consumed == 0) {
+			switch (current) {
+				case 'N': case 'n': degrees = 0; break;
+				case 'E': case 'e': degrees = 90; break;
+				case 'S': case 's': degrees = 180; break;
+				case 'W': case 'w': degrees = 270; break;
+			}
+			_wrap(&degrees);
+			continue;
+		}
+
+		factor /= 2;
+		switch (current) {
+			case 'N': case 'n':
+				if (degrees >= 180) {
+					degrees += factor;
+				} else {
+					degrees -= factor;
+				}
+
+				_clamp(0, 360, &degrees);
+				break;
+			case 'S': case 's':
+				if (degrees >= 0 && degrees < 180) {
+					degrees += factor;
+
+					_clamp(0, 180, &degrees);
+				} else {
+					degrees -= factor;
+
+					_clamp(180, 360, &degrees);
+				}
+				break;
+			case 'W': case 'w':
+				if (degrees >= 90 && degrees < 270) {
+					// Covers the bottom-arc
+					degrees += factor;
+					_clamp(90, 270, &degrees);
+				} else if (degrees < 90 && degrees < factor) {
+					// Covers the top-right quadrant
+					degrees = 360 - (factor - degrees);
+				} else {
+					degrees -= factor;
+					_clamp(0, 360, &degrees);
+				}
+				break;
+			case 'E': case 'e':
+				if (degrees >= 270 || degrees < 90) {
+					degrees += factor;
+					_wrap(&degrees);
+				} else {
+					degrees -= factor;
+					_wrap(&degrees);
+				}
+				break;
+		}
+	} while (++consumed);
+
+	return 0.0;
+}
+
+#endif // SENSELESS_H
\ No newline at end of file
diff --git a/test.c b/test.c
new file mode 100644
index 0000000..d414038
--- /dev/null
+++ b/test.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <string.h>
+#include <float.h>
+#include <math.h>
+
+#include "senseless.h"
+
+double assert(const char *directions, double expected) {
+	size_t len = strlen(directions);
+	double degrees = senseless_directions(directions, len);
+
+	if (fabs(degrees - expected) <= DBL_EPSILON) {
+		printf("✅ ");
+	} else {
+		printf("❌ ");
+	}
+	printf("%s = %.2f\n", directions, expected);
+
+	return degrees;
+}
+
+int main(int argc, char **argv) {
+	// Cardinal
+	printf("== Cardinal ==\n");
+	assert("N", 0.0);
+	assert("E", 90.0);
+	assert("S", 180.0);
+	assert("W", 270.0);
+
+	// Ordinal
+	printf("\n=== Ordinal ==\n");
+	assert("NE", 45.0);
+	assert("SE", 135.0);
+	assert("SW", 225.0);
+	assert("NW", 315.0);
+
+	// Gross
+	printf("\n==== Gross ===\n");
+	printf("(pulls clockwise)\n");
+	assert("NS", 45.0);
+	assert("SN", 225.0);
+	assert("EW", 135.0);
+	assert("WE", 315.0);
+
+	// Exciting
+	printf("\n== Exciting ==\n");
+	assert("NNW", 337.5);
+	assert("SEESE", 118.125);
+	assert("NESW", 56.25);
+}
\ No newline at end of file