add sorter with respecting testcase collections

This commit is contained in:
ІО-23 Шмуляр Олег 2024-12-12 19:59:08 +02:00
parent e80aa55375
commit ec5f4f6543
7 changed files with 174 additions and 27 deletions

View File

@ -4,12 +4,15 @@ build: main
test: tester test: tester
tester: out/tester.o out/swapper.o tester: out/tester.o out/sorter.o
gcc $(CFLAGS) out/tester.o out/swapper.o -o tester gcc $(CFLAGS) out/tester.o out/sorter.o -o tester
out/tester.o: out/ src/tester.c out/tester.o: out/ src/tester.c
gcc $(CFLAGS) -c src/tester.c -o out/tester.o gcc $(CFLAGS) -c src/tester.c -o out/tester.o
out/sorter.o: out/ src/sorter.c
gcc $(CFLAGS) -c src/sorter.c -o out/sorter.o
out/: out/:
mkdir out/ mkdir out/

1
inc/sorter.h Normal file
View File

@ -0,0 +1 @@
void sorter_insertion_sort(char **arr, int size);

44
src/sorter.c Normal file
View File

@ -0,0 +1,44 @@
#include <string.h>
#include "sorter.h"
#define MIN(a, b) ( ((a) < (b)) ? (a) : (b) )
static int lt(char *a, char *b)
{
int len_a = strlen(a);
int len_b = strlen(b);
for (int i = 0; i < MIN(len_a, len_b); i++) {
if (a[i] < b[i])
return 1;
else if (a[i] > b[i])
return -1;
}
return (len_a > len_b);
}
static void swap(char **arr, int x, int y)
{
char *tmp = arr[x];
arr[x] = arr[y];
arr[y] = tmp;
}
void sorter_insertion_sort(char **arr, int len)
{
for (int i = 0; i < len-1; i++) {
char *min = arr[i];
int min_index = i;
for (int j = i+1; j < len; j++) {
if (lt(arr[j], min) == 1) {
min_index = j;
min = arr[j];
}
}
if (min_index != i)
swap(arr, i, min_index);
}
}

View File

@ -1,12 +1,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include "swapper.h" #include "sorter.h"
enum read_state { enum read_state {
LEN = 0, LEN = 0,
STR1 = 1, ARR1 = 1,
STR2 = 2, ARR2 = 2,
FINISH = 3, FINISH = 3,
IMPOSSIBLE_STATE = 4 IMPOSSIBLE_STATE = 4
}; };
@ -44,30 +46,55 @@ static int read_more(int f, char *buf, int bytes_read)
return 1024 - bytes_read + new_bytes; return 1024 - bytes_read + new_bytes;
} }
static int parse_case(char *cmd, int *target_length_diff, char *str_a, char *str_b) static int parse_case(char *cmd, int *array_size, char ***a, char ***b)
{ {
int bytes_read; int bytes_read;
int write_offset = 0; int write_offset = 0;
int array_offset = 0;
char len_buffer[4] = {0}; char len_buffer[4] = {0};
enum read_state rs = LEN; enum read_state rs = LEN;
for (bytes_read = 0; bytes_read < 1024; bytes_read++) { for (bytes_read = 0; bytes_read < 1024; bytes_read++) {
switch (cmd[bytes_read]) { switch (cmd[bytes_read]) {
case ',':
switch (rs) {
case ARR1:
(*a)[array_offset][write_offset] = '\0';
break;
case ARR2:
(*b)[array_offset][write_offset] = '\0';
break;
}
write_offset = 0;
array_offset++;
break;
case ' ': case ' ':
switch (rs) { switch (rs) {
case LEN: case LEN:
*target_length_diff = to_int(len_buffer); *array_size = to_int(len_buffer);
*a = (char **) malloc(sizeof(char *) * (*array_size));
*b = (char **) malloc(sizeof(char *) * (*array_size));
for (int i = 0; i < *array_size; i++) {
(*a)[i] = malloc(sizeof(char) * 128);
(*b)[i] = malloc(sizeof(char) * 128);
}
break; break;
case STR1: case ARR1:
str_a[write_offset] = '\0'; (*a)[array_offset][write_offset] = '\0';
break; break;
} }
rs++; rs++;
write_offset = 0; write_offset = 0;
array_offset = 0;
break; break;
case '\n': case '\n':
str_b[write_offset] = '\0'; (*b)[array_offset][write_offset] = '\0';
bytes_read++; bytes_read++;
goto finish; goto finish;
break; break;
@ -77,11 +104,11 @@ static int parse_case(char *cmd, int *target_length_diff, char *str_a, char *str
case LEN: case LEN:
len_buffer[write_offset] = cmd[bytes_read]; len_buffer[write_offset] = cmd[bytes_read];
break; break;
case STR1: case ARR1:
str_a[write_offset] = cmd[bytes_read]; (*a)[array_offset][write_offset] = cmd[bytes_read];
break; break;
case STR2: case ARR2:
str_b[write_offset] = cmd[bytes_read]; (*b)[array_offset][write_offset] = cmd[bytes_read];
break; break;
} }
write_offset++; write_offset++;
@ -93,30 +120,90 @@ static int parse_case(char *cmd, int *target_length_diff, char *str_a, char *str
return bytes_read; return bytes_read;
} }
static int assert_length(int test_id, int target_length_diff, char *a, char *b) static void destroy_array(char **a, int array_size)
{ {
int len_diff = swapper_length_difference(a, b); for (int i = 0; i < array_size; i++)
free(a[i]);
if (len_diff == target_length_diff) { free(a);
}
static int cmp_arrays(int array_size, char **a, char **b)
{
int mismatch_byte = 0;
for (int i = 0; i < array_size; i++, mismatch_byte++) {
int la = strlen(a[i]);
int lb = strlen(b[i]);
if (la != lb)
return mismatch_byte;
for (int j = 0; j < la; j++, mismatch_byte++) {
if (a[i][j] != b[i][j])
return mismatch_byte;
}
}
return -1;
}
static void print_array(int array_size, char **arr)
{
for (int i = 0; i < array_size; i++)
printf("%s ", arr[i]);
puts("");
}
static void print_mismatch(int position)
{
for (int i = 0; i < position; i++)
fputs(" ", stdout);
puts("^");
for (int i = 0; i < position; i++)
fputs(" ", stdout);
puts("sort mismatch");
}
static int assert_sort(int test_id, int array_size, char **a, char **b)
{
sorter_insertion_sort(a, array_size);
int result = cmp_arrays(array_size, a, b);
if (result == -1) {
printf("[TEST#%02d] OK\r", test_id); printf("[TEST#%02d] OK\r", test_id);
return 0; return 0;
} else { } else {
printf("\n[TEST#%02d] FAILED!\n", test_id); printf("\n[TEST#%02d] FAILED!\n", test_id);
printf("Case details:\n"); printf("Case details:\n");
printf("Str1: %s\n", a); printf("Retrieved array: ");
printf("Str2: %s\n", b); print_array(array_size, a);
printf("Mismatch: %d expected, %d retrieved\n", target_length_diff, len_diff);
printf("Expected array: ");
print_array(array_size, b);
print_mismatch(result + 17);
return 1; return 1;
} }
} }
int main(int argc, char **argv)
int main(void)
{ {
int success_tests_counter = 0; int success_tests_counter = 0;
int failed_tests_counter = 0; int failed_tests_counter = 0;
int f = open("test/testcases_len", O_RDONLY); int f;
if (argc == 2)
f = open(argv[1], O_RDONLY);
else
f = open("test/testcases_sort_official", O_RDONLY);
if (f < 0) if (f < 0)
return 1; return 1;
@ -126,16 +213,20 @@ int main(void)
remaining_buffer_length = read(f, cmd, 1024); remaining_buffer_length = read(f, cmd, 1024);
while (remaining_buffer_length) { while (remaining_buffer_length) {
char str_a[1024], str_b[1024]; char **a, **b;
int target_length_diff; int array_size;
int bytes_read = parse_case(cmd, &target_length_diff, str_a, str_b); int bytes_read = parse_case(cmd, &array_size, &a, &b);
if (assert_length(success_tests_counter + failed_tests_counter + 1, target_length_diff, str_a, str_b)) if (assert_sort(success_tests_counter + failed_tests_counter + 1, array_size, a, b))
failed_tests_counter++; failed_tests_counter++;
else else
success_tests_counter++; success_tests_counter++;
// clean up before next iteration
destroy_array(a, array_size);
destroy_array(b, array_size);
if (remaining_buffer_length == 1024) if (remaining_buffer_length == 1024)
remaining_buffer_length = read_more(f, cmd, bytes_read); remaining_buffer_length = read_more(f, cmd, bytes_read);
else else

View File

@ -0,0 +1,2 @@
3 banana,apple,egg apple,banana,egg
4 banana,test,apple,egg apple,banana,egg,test

View File

@ -0,0 +1,5 @@
5 banana,apple,cherry,date,elderberry apple,banana,cherry,date,elderberry
1 hello hello
3 alpha,beta,gamma alpha,beta,gamma
3 gamma,beta,alpha alpha,beta,gamma
8 hello,world,foo,bar,baz,qux,quux,corge bar,baz,corge,foo,hello,quux,qux,world

View File

@ -0,0 +1 @@
3 1,2,3 2,1,3