diff --git a/makefile b/makefile index cb05ca2..5654302 100644 --- a/makefile +++ b/makefile @@ -37,6 +37,7 @@ $(program_obj_files): %.o: %.c # -------------------------- TEST_STACK_SOURCES = stack.c test_stack.c $(unityfolder)/unity.c TEST_BINTREE_SOURCES = bintree.c test_bintree.c stack.c $(unityfolder)/unity.c +TEST_NUMBERS_SOURCES = stack.c numbers.c bintree.c $(unityfolder)/unity.c test_numbers.c stackTests: $(TEST_STACK_SOURCES) stack.h $(CC) $(CFLAGS) -I$(unityfolder) $(TEST_STACK_SOURCES) -o runStackTests @@ -46,6 +47,10 @@ bintreeTests: $(TEST_BINTREE_SOURCES) stack.h bintree.h $(CC) $(CFLAGS) -I$(unityfolder) $(TEST_BINTREE_SOURCES) -o runBintreeTests ./runBintreeTests +numbersTests: $(TEST_NUMBERS_SOURCES) stack.h bintree.h numbers.h + $(CC) $(CFLAGS) -I$(unityfolder) $(TEST_NUMBERS_SOURCES) -o runNumbersTests + ./runNumbersTests + # -------------------------- # Clean # -------------------------- diff --git a/numbers.c b/numbers.c index f59d9a2..e8e79b4 100644 --- a/numbers.c +++ b/numbers.c @@ -5,22 +5,82 @@ #include "numbers.h" #include "bintree.h" -//TODO: getDuplicate und createNumbers implementieren +static int compareInt(const void *ptr1, const void *ptr2); + +// TODO: getDuplicate und createNumbers implementieren /* * * Erzeugen eines Arrays mit der vom Nutzer eingegebenen Anzahl an Zufallszahlen. - * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. - * Duplizieren eines zufälligen Eintrags im Array. - * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ + * Sicherstellen, dass beim Befüllen keine Duplikate entstehen. + * Duplizieren eines zufälligen Eintrags im Array. + * in `getDuplicate()`: Sortieren des Arrays und Erkennen der doppelten Zahl durch Vergleich benachbarter Elemente. */ // Returns len random numbers between 1 and 2x len in random order which are all different, except for two entries. // Returns NULL on errors. Use your implementation of the binary search tree to check for possible duplicates while // creating random numbers. + +/* +the implemented tree can't efficiently check if it contains a specific number, but we don't actually need that anyways +create numbers just counts and checks if the just inserted number sets the isDuplicate pointer +*/ +// srand should have been called before this function unsigned int *createNumbers(unsigned int len) { + unsigned int *randomNumbers = malloc(len * sizeof(int)); + // including upper limit + int upperLimit = len * 2; + + int numberCnt = 0; + + int isDuplicate = 0; + TreeNode *root = NULL; + // we only need len-1 numbers because 1 will be duplicated + while (numberCnt < len - 1) + { + // numbers up to and including upperLimit without 0 + int randNum = rand() % upperLimit + 1; + // reset isDuplicate + isDuplicate = 0; + // don't forget to set the root here + root = addToTree(root, &randNum, sizeof(randNum), (CompareFctType)compareInt, &isDuplicate); + if (isDuplicate) + { + // number already exists + continue; + } + randomNumbers[numberCnt++] = randNum; + } + + // select which number to duplicate + int dupNum = randomNumbers[rand() % numberCnt]; + // ...and where to insert + int dupNumIdx = rand() % len; + + // move the number currently at the dupNumIdx to the end + // and insert the dupNum at the index + // this also works if the last idx was selected for dupNum + randomNumbers[len - 1] = randomNumbers[dupNumIdx]; + randomNumbers[dupNumIdx] = dupNum; + + // clean up memory + clearTree(root); + return randomNumbers; } // Returns only the only number in numbers which is present twice. Returns zero on errors. unsigned int getDuplicate(const unsigned int numbers[], unsigned int len) { + qsort((void *)numbers, len, sizeof(int), compareInt); // sort the array + for (int i = 0; i < len - 1; i++) + { + if (numbers[i] == numbers[i + 1]) + return numbers[i]; + } + return 0; // zero on errors +} +static int compareInt(const void *ptr1, const void *ptr2) +{ + int num1 = *(int *)ptr1; + int num2 = *(int *)ptr2; + return num1 - num2; } \ No newline at end of file diff --git a/test_numbers.c b/test_numbers.c new file mode 100644 index 0000000..a7e6872 --- /dev/null +++ b/test_numbers.c @@ -0,0 +1,50 @@ +#include "unity.h" +// #include "bintree.h" +// #include "string.h" +#include "numbers.h" +#include "stdlib.h" + +void setUp(void) +{ + // set stuff up here +} + +void tearDown(void) +{ + // set stuff up here +} + +// getDuplicate on array without duplicats +// expects 0/error +void test_get_duplicate_error(void) +{ + unsigned int input[] = {1, 5, 9, 2, 4}; + unsigned int len = sizeof(input) / sizeof(input[0]); + + TEST_ASSERT_EQUAL_UINT(0, getDuplicate(input, len)); +} + +// this tries to brute force a triple +void test_for_triple(void) +{ + // this test is less effective if srand is called inside createNumbers() + for (int i = 0; i < 100000; i++) + { + unsigned int *numbers = createNumbers(3); + if (numbers[0] == numbers[1] && numbers[1] == numbers[2]) + { + // fail the test + TEST_ASSERT(0); + } + free(numbers); + } +} + +int main(void) +{ + printf("============================\nNumbers tests\n============================\n"); + UNITY_BEGIN(); + RUN_TEST(test_get_duplicate_error); + RUN_TEST(test_for_triple); + return UNITY_END(); +} \ No newline at end of file