1 Commits
Author SHA1 Message Date
wiesendsi102436 e4477b08dc set the seed for the RNG just once at the beginning of the program
this improves randomness for tests where createNumbers() is called in rapid succession
2025-11-30 09:11:32 +01:00
4 changed files with 14 additions and 119 deletions
-2
View File
@@ -1,6 +1,5 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "numbers.h"
#include "timer.h"
#include "highscore.h"
@@ -87,7 +86,6 @@ int main(int argc, char *argv[])
saveHighscores(highscorePath);
clearHighscores();
free(numbers);
exitCode = EXIT_SUCCESS;
}
+4 -23
View File
@@ -26,11 +26,6 @@ unsigned int *createNumbers(unsigned int len)
{
unsigned int *randomNumbers = malloc(len * sizeof(int));
if (!randomNumbers)
{
return NULL;
}
// including upper limit
int upperLimit = len * 2;
@@ -74,27 +69,13 @@ unsigned int *createNumbers(unsigned int len)
// 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)
{
unsigned int *numbersCpy = malloc(sizeof(unsigned int) * len);
if (!numbersCpy)
{
return 0;
}
memcpy(numbersCpy, numbers, len * sizeof(unsigned int));
numbersCpy = numbersCpy; // shadow the numbers array with copy
qsort((void *)numbersCpy, len, sizeof(int), compareInt); // sort the array
unsigned int duplicateFound = 0; // zero on errors
qsort((void *)numbers, len, sizeof(int), compareInt); // sort the array
for (int i = 0; i < len - 1; i++)
{
if (numbersCpy[i] == numbersCpy[i + 1])
{
duplicateFound = numbersCpy[i];
break;
}
if (numbers[i] == numbers[i + 1])
return numbers[i];
}
free(numbersCpy);
return duplicateFound;
return 0; // zero on errors
}
static int compareInt(const void *ptr1, const void *ptr2)
+6 -83
View File
@@ -1,9 +1,8 @@
#include "unity.h"
// #include "bintree.h"
// #include "string.h"
#include "numbers.h"
#include "stdlib.h"
#include "string.h"
static int compareInt(const void *ptr1, const void *ptr2);
void setUp(void)
{
@@ -17,7 +16,7 @@ void tearDown(void)
// getDuplicate on array without duplicats
// expects 0/error
void test_get_duplicate_without_duplicates(void)
void test_get_duplicate_error(void)
{
unsigned int input[] = {1, 5, 9, 2, 4};
unsigned int len = sizeof(input) / sizeof(input[0]);
@@ -25,21 +24,6 @@ void test_get_duplicate_without_duplicates(void)
TEST_ASSERT_EQUAL_UINT(0, getDuplicate(input, len));
}
// getDuplicate() on some arrays with 1 duplicate
void test_get_duplicate(void)
{
unsigned int arr1[] = {4, 15, 32, 5, 3, 8, 8};
unsigned int len1 = sizeof(arr1) / sizeof(arr1[0]);
unsigned int arr2[] = {1, 3, 3, 7};
unsigned int len2 = sizeof(arr2) / sizeof(arr2[0]);
unsigned int arr3[] = {7, 7, 8, 4, 9, 1};
unsigned int len3 = sizeof(arr3) / sizeof(arr3[0]);
TEST_ASSERT_EQUAL_UINT(8, getDuplicate(arr1, len1));
TEST_ASSERT_EQUAL_UINT(3, getDuplicate(arr2, len2));
TEST_ASSERT_EQUAL_UINT(7, getDuplicate(arr3, len3));
}
// this tries to brute force a triple
void test_for_triple(void)
{
@@ -49,79 +33,18 @@ void test_for_triple(void)
unsigned int *numbers = createNumbers(3);
if (numbers[0] == numbers[1] && numbers[1] == numbers[2])
{
TEST_FAIL_MESSAGE("triple generated");
// fail the test
TEST_ASSERT(0);
}
free(numbers);
}
}
// check if getDuplicate() modifies the original array (it should not)
void test_get_duplicate_does_modify()
{
unsigned int arr1[] = {1, 2, 3, 4, 5, 4, 3, 2, 1}; // sorting would change this
size_t len1 = sizeof(arr1) / sizeof(arr1[0]);
unsigned int arr1Copy[9];
memcpy(arr1Copy, arr1, len1 * sizeof(unsigned int));
getDuplicate(arr1, len1); // return value does not matter
// check if the arrays are still the same
if (memcmp(arr1, arr1Copy, len1 * sizeof(unsigned int)))
{
TEST_FAIL_MESSAGE("Arrays have diverged");
}
}
// checks if there is exactly 1 duplicate number at varying array sizes
void test_exactly_one_duplicate()
{
const size_t MAX_LIST_SIZE = 20; // max tested array len
const size_t ITERATIONS_PER_LEN = 20; // number of iterations for each tested array len
for (size_t len = 2; len < MAX_LIST_SIZE; len++) // start with smallest sensible size 2
{
for (size_t i = 0; i < ITERATIONS_PER_LEN; i++)
{
unsigned int *randTestList = createNumbers((unsigned int)len);
qsort(randTestList, len, sizeof(unsigned int), compareInt);
int cntDuplicate = 0;
for (size_t j = 0; j < len - 1; j++)
{
if (randTestList[j] == randTestList[j + 1])
{
cntDuplicate++;
}
}
// there should be exactly 1 duplicate
TEST_ASSERT_EQUAL_INT(1, cntDuplicate);
free(randTestList);
}
}
}
static int compareInt(const void *ptr1, const void *ptr2)
{
unsigned int num1 = *(int *)ptr1;
unsigned int num2 = *(int *)ptr2;
if (num1 < num2)
return -1;
if (num1 > num2)
return 1;
return 0;
}
int main(void)
{
printf("============================\nNumbers tests\n============================\n");
UNITY_BEGIN();
RUN_TEST(test_get_duplicate_without_duplicates);
RUN_TEST(test_get_duplicate_error);
RUN_TEST(test_for_triple);
RUN_TEST(test_exactly_one_duplicate);
RUN_TEST(test_get_duplicate);
RUN_TEST(test_get_duplicate_does_modify);
return UNITY_END();
}
+4 -11
View File
@@ -1,12 +1,6 @@
#include "timer.h"
#ifdef __linux__
// Defines strict posix compliance for CLOCK_MONOTONIC
#define _POSIX_C_SOURCE 199309L
#include <time.h>
#endif
#if __APPLE__ || __linux__
#if __APPLE__
#include <sys/time.h>
static struct timespec start = {0, 0};
@@ -20,15 +14,14 @@ void startTimer()
double stopTimer()
{
struct timespec end;
clock_gettime(CLOCK_MONOTONIC, &end);
unsigned long long delta_us = (end.tv_sec - start.tv_sec) * 1000000 + (end.tv_nsec - start.tv_nsec) / 1000;
double measuredSeconds = (double)delta_us / 1000000.;
if (start.tv_nsec > 0)
{
if(start.tv_nsec > 0) {
start.tv_nsec = 0;
start.tv_sec = 0;
}
@@ -52,7 +45,7 @@ double stopTimer()
{
double measuredSeconds = (clock() - (double)startClocks) / CLOCKS_PER_SEC;
if (startClocks > 0)
if(startClocks > 0)
startClocks = 0;
else
measuredSeconds = -1;