From 45e804a35088574bf117fc0f746c886b197bb594 Mon Sep 17 00:00:00 2001 From: bronku Date: Wed, 15 Oct 2025 16:34:25 +0200 Subject: [PATCH] quicksort --- TODO.md | 2 +- main.c | 16 +++++++++++- makefile | 15 +++++++++-- record.h | 16 +++++++----- tape.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ tape.h | 6 ++--- tests/1.in | 2 +- 7 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 tape.c diff --git a/TODO.md b/TODO.md index a5571cd..add9ff1 100644 --- a/TODO.md +++ b/TODO.md @@ -4,7 +4,7 @@ - [ ] a tape type - representing a file? - [x] a record type - x1,x2,x3,x4,x5 - [x] comparing records -- [ ] buffer merge sort +- [x] buffer quick sort - [x] configuration - [x] cmd args - man getopts - [x] file input diff --git a/main.c b/main.c index 5173cd7..bd1df1d 100644 --- a/main.c +++ b/main.c @@ -1,3 +1,5 @@ +#include "record.h" +#include "tape.h" #include #include #include @@ -81,7 +83,7 @@ int process_args(int argc, char** argv, options* opts) fprintf(stderr, "No file specified, aborting\n"); return ERROR; } - opts->input = fopen(filename, "a+"); + opts->input = fopen(filename, "r"); if (!opts->input) { fprintf(stderr, "Error: Cannot open file '%s'\n", filename); return ERROR; @@ -99,6 +101,18 @@ void write_file(options* opts) void sort_file(options* opts) { + tape a = { 0, 0, opts->input }; + buffer buff; + buff.capacity = 100; + buff.location = malloc(sizeof(record) * buff.capacity); + int status = read_buffer(&buff, &a); + if (status != SUCCESS && status != EOF) { + printf("Error reading file: %d\n", status); + } + fclose(a.file); + a.file = stdout; + sort_buffer(&buff); + free(buff.location); } int main(int argc, char** argv) diff --git a/makefile b/makefile index fa51403..96b2bee 100644 --- a/makefile +++ b/makefile @@ -1,5 +1,13 @@ -build/main: main.c build - clang main.c -o build/main +CFLAGS = -g + +build/main: build/main.o build/tape.o build + clang $(CFLAGS) build/main.o build/tape.o -o build/main + +build/main.o: main.c build + clang $(CFLAGS) -c main.c -o build/main.o + +build/tape.o: tape.c build + clang $(CFLAGS) -c tape.c -o build/tape.o build: mkdir -p build @@ -10,4 +18,7 @@ clean: run: build/main build/main -f tests/1.in +debug: build/main + lldb -- build/main -f tests/1.in + .PHONY: clean run diff --git a/record.h b/record.h index de3d0c2..bbd1d11 100644 --- a/record.h +++ b/record.h @@ -1,5 +1,6 @@ #pragma once #include +#include typedef struct { int a[5]; @@ -21,21 +22,24 @@ static inline int compare_records(const void* a, const void* b) { const record* ra = (const record*)a; const record* rb = (const record*)b; - const int ga = g(ra); - const int gb = g(rb); - return (ga > gb) - (ga < gb); + int ga = g(ra); + int gb = g(rb); + int result = (ga > gb) - (ga < gb); + return result; } static inline void print_record(FILE* stream, const record* out) { - fprintf(stream, "[%d %d %d %d %d] x=%d, g=%d", - out->a[0], out->a[1], out->a[2], out->a[3], out->a[4], out->x, g(out)); + fprintf(stream, "%d %d %d %d %d %d", + out->a[0], out->a[1], out->a[2], out->a[3], out->a[4], out->x); } static inline int read_record(FILE* stream, record* out) { - int result = fscanf(stream, "%d %d %d %d %d %d", &out->a[0], &out->a[1], &out->a[2], &out->a[3], &out->a[4], &out->x); + record tmp; + int result = fscanf(stream, "%d %d %d %d %d %d", &tmp.a[0], &tmp.a[1], &tmp.a[2], &tmp.a[3], &tmp.a[4], &tmp.x); if (result == 6) { + *out = tmp; return 0; } if (result == EOF) { diff --git a/tape.c b/tape.c new file mode 100644 index 0000000..6abcaf7 --- /dev/null +++ b/tape.c @@ -0,0 +1,75 @@ +#include "record.h" +#include "tape.h" + +int partition(record* arr, int start, int end) +{ + int i = start; + record* pivot = arr; + pivot += end; + for (int j = start; j < end; j++) { + record* current = arr; + current += j; + if (compare_records(current, pivot) > 0) { + continue; + } + record* i_rec = arr; + i_rec += i; + record tmp = *i_rec; + *i_rec = *current; + *current = tmp; + i++; + } + record* i_rec = arr; + i_rec += i; + record tmp = *i_rec; + *i_rec = *pivot; + *pivot = tmp; + return i; +} + +void quicksort(record* arr, int start, int end, int depth) +{ + if (start >= end || start < 0) { + return; + } + + int p = partition(arr, start, end); + quicksort(arr, start, p - 1, depth + 1); + quicksort(arr, p + 1, end, depth + 1); +} + +void sort_buffer(buffer* buff) +{ + quicksort(buff->location, 0, buff->length - 1, 0); +} + +int read_buffer(buffer* buff, tape* tape) +{ + int status; + record* destination = buff->location; + buff->length = 0; + while (buff->capacity > buff->length) { + status = read_record(tape->file, destination); + if (status != 0) { + return status; + } + destination++; + buff->length++; + tape->reads++; + } + return 0; +} + +int write_buffer(buffer* buff, tape* tape) +{ + record* current = buff->location; + record* last = current; + last += buff->length; + while (current < last) { + print_record(tape->file, current); + fprintf(tape->file, "\n"); + current++; + tape->reads++; + } + return 0; +} diff --git a/tape.h b/tape.h index bb58997..2a064c7 100644 --- a/tape.h +++ b/tape.h @@ -14,11 +14,11 @@ typedef struct { } buffer; // sorts the entire buffer -void quicksort(buffer* buff); +void sort_buffer(buffer* buff); // reads [capacity] records -void read_buffer(buffer* buff, tape* tape); +int read_buffer(buffer* buff, tape* tape); // writes everything -void write_buffer(buffer* buff, tape* tape); +int write_buffer(buffer* buff, tape* tape); void clear_tape(tape* tape); diff --git a/tests/1.in b/tests/1.in index 062d8c2..75c707a 100644 --- a/tests/1.in +++ b/tests/1.in @@ -1,4 +1,4 @@ -12312 312312 312 312 323 3 +11 123 312 312 323 3 543 3435 34 5342 532 54 344 43534 222 435 2345 23 2345 234 23423 455 44 4