add sorter with respecting testcase collections
This commit is contained in:
parent
e80aa55375
commit
ec5f4f6543
7
Makefile
7
Makefile
|
@ -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/
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
void sorter_insertion_sort(char **arr, int size);
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
141
src/tester.c
141
src/tester.c
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
3 banana,apple,egg apple,banana,egg
|
||||||
|
4 banana,test,apple,egg apple,banana,egg,test
|
|
@ -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
|
|
@ -0,0 +1 @@
|
||||||
|
3 1,2,3 2,1,3
|
Loading…
Reference in New Issue