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
 | 
			
		||||
 | 
			
		||||
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
									
								
							
							
						
						
									
										1
									
								
								inc/sorter.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
void sorter_insertion_sort(char **arr, int size);
 | 
			
		||||
							
								
								
									
										44
									
								
								src/sorter.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/sorter.c
									
									
									
									
									
										Normal 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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										141
									
								
								src/tester.c
									
									
									
									
									
								
							
							
						
						
									
										141
									
								
								src/tester.c
									
									
									
									
									
								
							@ -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
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								test/testcases_sort_custom
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test/testcases_sort_custom
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
			
		||||
3 banana,apple,egg apple,banana,egg
 | 
			
		||||
4 banana,test,apple,egg apple,banana,egg,test
 | 
			
		||||
							
								
								
									
										5
									
								
								test/testcases_sort_official
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								test/testcases_sort_official
									
									
									
									
									
										Normal 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
 | 
			
		||||
							
								
								
									
										1
									
								
								test/testcases_sort_wrong
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/testcases_sort_wrong
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
			
		||||
3 1,2,3 2,1,3
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user