From 759ecb151eba90f47475d7cf90f837cd4f6fb069 Mon Sep 17 00:00:00 2001 From: Daniel Bulant Date: Mon, 2 Dec 2024 22:48:46 +0100 Subject: [PATCH] first attempt at sort --- 2024/c/01.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 98 insertions(+), 5 deletions(-) diff --git a/2024/c/01.c b/2024/c/01.c index a7f09e9..bbfb0ee 100644 --- a/2024/c/01.c +++ b/2024/c/01.c @@ -35,6 +35,8 @@ void DS_grow(struct DynSlice* slice, usize newcap) { usize cap = slice->capacity; usize size = slice->size; + if(cap >= newcap) return; + void* dataptr = slice->data; if(cap == 0) cap = 1; @@ -58,6 +60,10 @@ void DS_debugprint(const struct DynSlice* slice) { printf("dynslice, size %li, cap %li, size of %li\n", slice->size, slice->capacity, slice->size_of); } +void* DS_iptr(struct DynSlice* slice, usize index) { + return slice->data + index * slice->size_of; +} + // Pushes a new object. Accepts a pointer to said object. Copies. // returns index of pushed data // assumes size_of from slice. Take care of types lol. @@ -67,15 +73,15 @@ usize DS_push(struct DynSlice* slice, void* ptr) { if(cap <= size) { DS_grow(slice, cap+1); } - memcpy(slice->data + slice->size * slice->size_of, ptr, slice->size_of); + memcpy(DS_iptr(slice, slice->size), ptr, slice->size_of); slice->size += 1; return size; } // Extends a slice from another array-like object void DS_extend(struct DynSlice* slice, void* ptr, usize count) { - if(slice->capacity < slice->size + count) DS_grow(slice, slice->size + count); - memcpy(slice->data + slice->size * slice->size_of, ptr, slice->size_of * count); + DS_grow(slice, slice->size + count); + memcpy(DS_iptr(slice, slice->size), ptr, slice->size_of * count); slice->size += count; } @@ -103,7 +109,7 @@ void DS_drop(struct DynSlice* slice) { // Gets pointer to a single element, checking it's size void* DS_get(const struct DynSlice* slice, const usize i) { - if(slice->size >= i) { + if(slice->size <= i) { panic("DS Get out of bounds"); } return slice->data + i * slice->size_of; @@ -144,15 +150,102 @@ struct DynSlice DS_line_from_file(FILE* input) { } } +// Swaps two indexes in place, using last element of vector (may grow the vector and cause alloc) +void DS_swap(struct DynSlice* slice, usize i, usize j) { + DS_grow(slice, slice->size + 1); + memcpy(DS_iptr(slice, slice->size), DS_iptr(slice, i), slice->size_of); + memcpy(DS_iptr(slice, i), DS_iptr(slice, j), slice->size_of); + memcpy(DS_iptr(slice, j), DS_iptr(slice, slice->size), slice->size_of); +} + +void DS_intdebugprint(struct DynSlice* slice) { + if(slice->size_of != sizeof(int)) panic("using int debug print on non-int"); + + DS_debugprint(slice); + printf("values: "); + for(usize i = 0; i < slice->size; i += 1) { + printf("%i ", *(int*)DS_get(slice, i)); + } + printf("\n"); +} + + +// Sorts the array between left and right +// Uses a compare function. Returning -1 means the left number is smaller, 0 =, 1 left > right +// quicksort impl based on https://www.youtube.com/watch?v=Hoixgm4-P4M +void DS_sort_sliced(struct DynSlice* slice, int (*compare)(void*, void*), usize left, usize right) { + if(right <= left) return; + + usize pivot = left; + usize len = right - left; + + DS_swap(slice, pivot, right); + pivot = right; + + while(1) { + usize itemFromLeft = left; + while(compare(DS_get(slice, itemFromLeft), DS_get(slice, pivot)) < 0) + itemFromLeft += 1; + + usize itemFromRight = right - 1; + while(compare(DS_get(slice, itemFromRight), DS_get(slice, pivot)) > 0) + itemFromRight -= 1; + + if(itemFromLeft < itemFromRight) { + DS_swap(slice, itemFromLeft, itemFromRight); + } else { + DS_swap(slice, itemFromLeft, pivot); + pivot = itemFromLeft; + DS_intdebugprint(slice); + break; + } + } +} + +// Sort the array using Quicksort +// Uses a compare function. Returning -1 means the left number is smaller, 0 =, 1 left > right +void DS_sort(struct DynSlice* slice, int (*compare)(void*, void*)) { + DS_sort_sliced(slice, compare, 0, slice->size); +} + +int intcompare(int* a, int* b) { + if(*a > *b) return 1; + if(*a == *b) return 0; + if(*a < *b) return -1; +} + int main(int argc, char *argv[]) { setvbuf(stdout, NULL, _IONBF, 0); const char* loc = argv[1]; printf("file %s\n", loc); FILE* input = fopen(loc, "r"); + + struct DynSlice left = DS_create(sizeof(int)); + struct DynSlice right = DS_create(sizeof(int)); + while(!feof(input)) { struct DynSlice line = DS_line_from_file(input); - printf("%s\n", (char*)line.data); + + // line is in a format of int int + // find space, add 2 to it. Then 0 - space is one int, space+3 - end is the other one. + // we do this by inserting a null byte to effectively split into two strings + + char* spaceptr = strchr(line.data, ' '); + *spaceptr = '\0'; + spaceptr += 3; + + int first = atoi(line.data); + DS_push(&left, &first); + int second = atoi(spaceptr); + DS_push(&left, &first); + DS_drop(&line); } + + DS_intdebugprint(&left); + DS_sort(&left, intcompare); + fclose(input); + DS_drop(&left); + DS_drop(&right); } \ No newline at end of file