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
tester: out/tester.o out/swapper.o
gcc $(CFLAGS) out/tester.o out/swapper.o -o tester
tester: out/tester.o out/sorter.o
gcc $(CFLAGS) out/tester.o out/sorter.o -o tester
out/tester.o: out/ src/tester.c
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/:
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 <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include "swapper.h"
#include "sorter.h"
enum read_state {
LEN = 0,
STR1 = 1,
STR2 = 2,
ARR1 = 1,
ARR2 = 2,
FINISH = 3,
IMPOSSIBLE_STATE = 4
};
@ -44,30 +46,55 @@ static int read_more(int f, char *buf, int bytes_read)
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 write_offset = 0;
int array_offset = 0;
char len_buffer[4] = {0};
enum read_state rs = LEN;
for (bytes_read = 0; bytes_read < 1024; 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 ' ':
switch (rs) {
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;
case STR1:
str_a[write_offset] = '\0';
case ARR1:
(*a)[array_offset][write_offset] = '\0';
break;
}
rs++;
write_offset = 0;
array_offset = 0;
break;
case '\n':
str_b[write_offset] = '\0';
(*b)[array_offset][write_offset] = '\0';
bytes_read++;
goto finish;
break;
@ -77,11 +104,11 @@ static int parse_case(char *cmd, int *target_length_diff, char *str_a, char *str
case LEN:
len_buffer[write_offset] = cmd[bytes_read];
break;
case STR1:
str_a[write_offset] = cmd[bytes_read];
case ARR1:
(*a)[array_offset][write_offset] = cmd[bytes_read];
break;
case STR2:
str_b[write_offset] = cmd[bytes_read];
case ARR2:
(*b)[array_offset][write_offset] = cmd[bytes_read];
break;
}
write_offset++;
@ -93,30 +120,90 @@ static int parse_case(char *cmd, int *target_length_diff, char *str_a, char *str
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);
return 0;
} else {
printf("\n[TEST#%02d] FAILED!\n", test_id);
printf("Case details:\n");
printf("Str1: %s\n", a);
printf("Str2: %s\n", b);
printf("Mismatch: %d expected, %d retrieved\n", target_length_diff, len_diff);
printf("Retrieved array: ");
print_array(array_size, a);
printf("Expected array: ");
print_array(array_size, b);
print_mismatch(result + 17);
return 1;
}
}
int main(void)
int main(int argc, char **argv)
{
int success_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)
return 1;
@ -126,16 +213,20 @@ int main(void)
remaining_buffer_length = read(f, cmd, 1024);
while (remaining_buffer_length) {
char str_a[1024], str_b[1024];
int target_length_diff;
char **a, **b;
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++;
else
success_tests_counter++;
// clean up before next iteration
destroy_array(a, array_size);
destroy_array(b, array_size);
if (remaining_buffer_length == 1024)
remaining_buffer_length = read_more(f, cmd, bytes_read);
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