#include #include #include #include #include "numbers.h" #include "bintree.h" //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. */ // Comparison function for unsigned integers used in the binary search tree // Returns: <0 if a < b, 0 if a == b, >0 if a > b // This function is passed to addToTree to determine ordering int compareUnsignedInts(const void *a, const void *b) { unsigned int valA = *(const unsigned int *)a; unsigned int valB = *(const unsigned int *)b; // Simple subtraction works for unsigned integers in this case // (Note: in general subtraction can overflow, but our range is small) if (valA < valB) return -1; if (valA > valB) return 1; return 0; } // 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. // // Algorithm: // 1. Generate len-1 unique random numbers using the BST for duplicate detection // 2. Randomly duplicate one of those numbers by inserting it at a random position // 3. Final array has len entries with exactly one value appearing twice unsigned int *createNumbers(unsigned int len) { // Step 1: Validate input - we need at least 2 elements to create a duplicate if (len < 2) { return NULL; } // Step 2: Allocate memory for the final array (len elements total) unsigned int *numbers = (unsigned int *)malloc(len * sizeof(unsigned int)); if (numbers == NULL) { return NULL; } // Step 3: Create binary search tree to track generated numbers and prevent accidental duplicates // Note: Random seed should be initialized once in main() with srand(time(NULL)) // Calling srand() here would reset the seed each time, reducing randomness TreeNode *usedNumbers = NULL; // Step 4: Generate len-1 unique random numbers (we'll add one duplicate later) unsigned int arrayIndex = 0; while (arrayIndex < len - 1) { // Generate random number in range [1, 2×len] unsigned int randomNumber = (rand() % (2 * len)) + 1; // Check if this number was already generated int isDuplicate = 0; usedNumbers = addToTree(usedNumbers, &randomNumber, sizeof(unsigned int), compareUnsignedInts, &isDuplicate); if (usedNumbers == NULL) { free(numbers); return NULL; } // If new number, add to result array; if duplicate, retry if (isDuplicate == 0) { numbers[arrayIndex] = randomNumber; arrayIndex++; } } // Step 5: Pick a random value from our generated numbers to duplicate unsigned int indexToDuplicate = rand() % (len - 1); unsigned int valueToDuplicate = numbers[indexToDuplicate]; // Step 6: Pick a random position to insert the duplicate (anywhere in the array) unsigned int insertPos = rand() % len; // Step 7: Shift elements right to make room for the duplicate for (unsigned int i = len - 1; i > insertPos; i--) { numbers[i] = numbers[i - 1]; } // Step 8: Insert the duplicate at the chosen position numbers[insertPos] = valueToDuplicate; // Step 9: Clean up the binary search tree (we don't need it anymore) clearTree(usedNumbers); // Return the array with len elements (len-1 unique + 1 duplicate) return numbers; } // Comparison function for qsort to sort unsigned integers in ascending order // Returns: <0 if a < b, 0 if a == b, >0 if a > b static int compareUnsigned(const void *a, const void *b) { unsigned int valA = *(const unsigned int *)a; unsigned int valB = *(const unsigned int *)b; if (valA < valB) return -1; if (valA > valB) return 1; return 0; } // Returns only the only number in numbers which is present twice. Returns zero on errors. // // Algorithm: // 1. Create a copy of the array to avoid modifying the input // 2. Sort the copy using qsort() // 3. Compare adjacent elements to find the duplicate // 4. Return the duplicate value, or 0 on error unsigned int getDuplicate(const unsigned int *numbers, unsigned int len) { // Step 1: Input validation - need at least 2 elements to have a duplicate if (numbers == NULL || len < 2) { return 0; } // Step 2: Create a copy of the array to sort (we don't modify the input) unsigned int *sorted = (unsigned int *)malloc(len * sizeof(unsigned int)); if (sorted == NULL) { return 0; } // Step 3: Copy the array memcpy(sorted, numbers, len * sizeof(unsigned int)); // Step 4: Sort the copy qsort(sorted, len, sizeof(unsigned int), compareUnsigned); // Step 5: Compare adjacent elements to find the duplicate for (unsigned int i = 0; i < len - 1; i++) { if (sorted[i] == sorted[i + 1]) { // Found the duplicate! unsigned int result = sorted[i]; free(sorted); return result; } } // Step 6: No duplicate found (should not happen if input is valid) free(sorted); return 0; }