I'm trying to make a rehashing function that will work on very large hash tables (with more than 1 million entries) and my current method is very inefficient. Here are my structures
typedef struct {
int id, count, correct, valid;
char* word;
} Entry;
typedef struct {
Entry* arr;
int size, numValid;
} Hash;
Here is how it functions now (very slowly, not using memcpy):
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = calloc(hash->size, sizeof(Entry));
for(i = 0; i < hash->size; i++) {
if(hash->arr[i].count) {
tempArr[i].count = hash->arr[i].count;
tempArr[i].correct = hash->arr[i].valid;
tempArr[i].word = malloc(strlen(hash->arr[i].word) + 1);
strcpy(tempArr[i].word,hash->arr[i].word);
tempLen++;
}
memcpy(&tempArr[i],&hash->arr[i],sizeof(Entry));
tempArr[i] = hash->arr[i];
}
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word,tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
I'd prefer to use memcpy, but I can't for the life of me get it to work correctly. Here's what I'm trying (this is the code that doesn't work, and what I'm looking for help with):
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = calloc(hash->size, sizeof(Entry));
fprintf(stderr,"size: %d\n",hash->size * sizeof(Entry));
memcpy((tempArr),(hash->arr),hash->size * sizeof(Entry));
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word,tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
I'm sure it's an easy, one-line fix, but I just can't get myself to see it.
void addEntry(Hash* hash, char* tag, int count) {
int value = CHV(hash->size, tag), flag = 1, iter = 0;
int possIndex = findEntry(hash, tag);
/*fprintf(stderr,"AddEntry...\n");*/
if(possIndex >= 0) {
(hash->arr[possIndex].count)++;
return;
}
if((hash->size - hash->numValid) < ((double)hash->size / 10))
{
rehash(hash);
}
while(flag) {
iter++;
if(!(hash->arr[value].valid)) {
hash->arr[value].word = calloc(strlen(tag) + 1, sizeof(char));
strcpy(hash->arr[value].word, tag);
wordsAlloced++;
hash->arr[value].valid = 1;
hash->arr[value].correct = 1;
hash->arr[value].count = count;
flag = 0;
}
else {
value++;
if(value == hash->size) {
value = 0;
}
}
}
hash->numValid++;
}
I think that memcpy is no problem. problem is free all Entry by removeAllEntries(hash); then tempArr[i].word is the double free in free(tempArr[i].word); Because it's copied pointer. Also Using tempArr[i].word in addEntry(hash,tempArr[i].word,tempArr[i].count); is invalid. It's already free'd.
One solution proposes the use of realloc.
replace
void resize(Hash* hash) {
free(hash->arr);
hash->size *= 2;
hash->arr = calloc(hash->size, sizeof(Entry));
//TOTALALLOC += (hash->size * sizeof(Entry));
}
with
void resize(Hash* hash) {
Entry* tempArr;
if((tempArr = realloc(hash->arr, 2 * hash->size * sizeof(Entry)))==NULL){
fprintf(stderr,"failed realloc in resize.\n");
return ;
}
hash->size *= 2;
hash->arr = tempArr;
//TOTALALLOC += (hash->size * sizeof(Entry));
}
Does not rehash for resizing purpose.
Another solution
If rehashing is necessary for some reason. to change in the following
void rehash(Hash* hash) {
Entry* tempArr;
int i;
tempArr = malloc(hash->size * sizeof(Entry));//Initialization isn't required because it is replaced by memcpy.
//fprintf(stderr,"size: %d\n",hash->size * sizeof(Entry));
memcpy(tempArr,hash->arr, hash->size * sizeof(Entry));
//To replicate word
for(i = 0; i < hash->size; i++) {
if(hash->arr[i].count) {
tempArr[i].word = malloc(strlen(hash->arr[i].word) + 1);
strcpy(tempArr[i].word, hash->arr[i].word);
}
}
removeAllEntries(hash);
resize(hash);
for(i = 0; i < (hash->size / 2); i++) {
if(tempArr[i].count > 0) {
addEntry(hash,tempArr[i].word, tempArr[i].count);
/*printf("Added %s with count %d\n",tempArr[i].word,tempArr[i].count);*/
free(tempArr[i].word);
}
}
free(tempArr);
}
If numValid is the represent the valid registration number, I think that it is sufficient to save only a word and count.
Related
I'm working with integer sequences with non-repeating elements, for some reasons I am tring to remove duplicates by building a hashset.
int * a = {123, 145, 210, 77};
int * b = {145, 77, 123, 210}; // should be removed
int * c = {123, 37, 16};
int * d = {123, 145, 72, 91};
Is there order insensitive hash functions that return same result for a and b?
I have come out of some solutions, but they performs poorly:
sorting - The sequences are immutable, sorting will invlove extra space and O(NlogN) time.
xor - The element in sequences ranges from 0 to hundreds, many bits of hash value may be wasted.
Is there other methods?
Hashing is not the only thing you should do. Because of information loss, completely different arrays could return the same hash. In order to only remove duplicates, you would need to check for equivalence too. A hashset does that too, but places the elements based on a hash, so you can find them more easily.
Here is an example implementation:
#include <stdlib.h>
#include <stdbool.h>
struct hashset {
int count;
int capacity;
struct hashset_element {
int hash;
int arrlen;
int *arrval;
} *elements;
};
void init_hashset(struct hashset *set) {
set->count = 0;
set->capacity = 0;
set->elements = NULL;
}
int hash(int *arr, int len) {
// you can replace this hash function
// this is a pretty simple one
int out = 0;
for (int i = 0; i < len; i++) {
out += arr[i];
}
return out;
}
void arrequals(int *arr1, int len1, int *arr2, int len2) {
if (len1 != len2)
return false;
arr1srt = sort(arr1, len1);
arr2srt = sort(arr2, len2);
for (int i = 0; i < len1; i++) {
if (arr1srt[i] != arr2srt[i])
free(arr1srt);
free(arr2srt);
return false;
}
free(arr1srt);
free(arr2srt);
return true;
}
bool hashset_contains(struct hashset *set, int *arr, int len) {
int rawhash = hash(arr, len);
int hash = rawhash % set->capacity;
for (int i = hash; i < set->capacity; i++) {
if (set->elements[i]->arrval == NULL)
return false;
if (arrequals(set->elements[i]->arrval,
set->elements[i]->arrlen, arr, len)
return true;
}
for (int i = 0; i < hash; i++) {
if (set->elements[i]->arrval == NULL)
return false;
if (set->elements[i]->hash == rawhash &&
arrequals(set->elements[i]->arrval,
set->elements[i]->arrlen, arr, len)
return true;
}
return false;
}
void hashset_realloc(struct hashset *set) {
struct hashset_element* oldarr = set->elements;
int old_capacity = set->capacity;
set->elements = malloc(sizeof(struct hash_element) * set->capacity + 1024);
set->capacity += 1024;
for (int i = 0; i < set->capacity; i++) {
if (oldarr[i]->arrval != NULL)
hashset_add_element(set, oldarr[i]->arrval, oldarr[i]->arrlen);
}
}
void hashset_add_element(struct hashset *set, int *arr, int len) {
if (!hashset_contains(set, arr, len)) {
if (set->count >= set->capacity / 2) {
realloc_hashset(set);
}
int rawhash = hash_element(arr, len);
int hash = rawhash % set->capacity;
for (int i = hash; i < set->capacity; i++) {
if (set->elements[i]->arrval == NULL) {
set->elements[i]->hash = rawhash;
set->elements[i]->arrval = arr;
set->elements[i]->arrlen = len;
set->count++;
return;
}
}
for (int i = 0; i < hash; i++) {
if (set->elements[i]->arrval == NULL) {
set->elements[i]->hash = rawhash;
set->elements[i]->arrval = arr;
set->elements[i]->arrlen = len;
set->count++;
return;
}
}
}
}
void destroy_hashset(struct hashset *set) {
if (set->elements != NULL)
free(set->elements);
}
int hashset_to_array(struct hashset *set, int **arrout, int *lenout, int maxlen) {
int w = 0;
for (int i = 0; i < capacity; i++) {
if (w >= maxlen)
break;
arrout[w] = set->elements[i]->arrval;
lenout[w] = set->elements[i]->arrlen;
w++;
}
return set->count;
}
I did not test this code, but give it a try and feel free to correct me, if there is an error in my code. You have to implement your sort function yourself. I don't know how big the arrays are, you are working with, so I can't pick an ideal algorithm for you. Order insensitive comparing is only possible in O(n*log(n)). O(n) is possible, if the integers have a maximum size, small enough to use a counting table.
In ideal cases this hashset has a runtime of O(1). The worst case runtime is O(n), which is very unlikely to happen. The hash algorithm has a runtime of O(n), which is not ideal but okay for small arrays.
In the following code, the result is ok, but the code will be crash when executing finish, and increase one error: Heap corruption detected, the free list is damaged at 0x600000008f50
int *mergeSort(int *a,int count) {
int leftCount = count / 2;
int rightCount = count - leftCount;
int *leftData = getData(a, 0, leftCount);
int *rightData = getData(a, leftCount, count);
int *sortedLeftData = mergeSort(leftData, leftCount);
int *sortedRightData = mergeSort(rightData, rightCount);
int *resultData = mergeData(sortedLeftData, sortedRightData, leftCount,
rightCount);
return resultData;
}
int *getData(int *a,int from, int to) {
if (from > to) { return nil; }
int *res = malloc(to - from + 1);
for (int index = from; index < to; index ++) {
int value = a[index];
res[index-from] = value;
}
return res;
}
int *mergeData(int *a, int *b, int acount, int bcount) {
int *result = malloc(acount + bcount);
int aindex,bindex,rindex;
aindex = bindex = rindex = 0;
while (aindex < acount | bindex < bcount) {
int value,avalue = INT_MAX,bvalue = INT_MAX;
if (aindex < acount) { avalue = a[aindex]; }
if (bindex < bcount) { bvalue = b[bindex]; }
// get value from a point.
if (avalue <= bvalue) {
value = avalue;
aindex ++;
}else {
// get value from b point.
value = bvalue;
bindex ++;
}
result[rindex] = value;
rindex ++;
}
return result;
}
I don't understand why does crash when free the point, any answer will helpfull, thanks.
All of your allocations are too small, and thus you are overflowing your buffers.
The malloc function allocates the requested number of bytes. You need to multiply the number of elements you require by sizeof(int) if your elements are int type. e.g.
int *result = malloc((acount + bcount) * sizeof(int));
Other potential problems I spotted while reading your code are:
Using the bitwise-or operator instead of logical-or:
while (aindex < acount | bindex < bcount)
// ^ should be ||
You never free your temporary buffers, thus your program will blow out memory by leaking like crazy. You must free leftData, rightData, sortedLeftData and sortedRightData in the mergeSort function after you are finished with them.
Note that merge sort actually does not require so much allocation. Doing so will have a huge impact on performance. An efficient implementation only requires a single additional buffer for scratch operations, which can be allocated at the beginning.
I did implementation merge sort use single buffer, as the following code:
void mergeSort(int *a, int count) {
int *tempBuffer = malloc(count * sizeof(int));
mergeSortWithBuffer(a, 0, 0, count - 1,tempBuffer);
free(tempBuffer);
}
void mergeSortWithBuffer(int *a, int leftStart, int rightStart, int end, int *tempBuffer) {
int leftCount = rightStart - leftStart;
int rightCount = end - rightStart + 1;
if (leftCount + rightCount <= 1) { return; }
if (leftCount != 0) {
// left dichotomy
int lls = leftStart;
int lrs = leftStart + leftCount/2;
int lnd = rightStart - 1;
mergeSortWithBuffer(a, lls, lrs, lnd,tempBuffer);
}
if (rightCount != 0) {
// right dichotomy
int rls = rightStart;
int rrs = rightStart + rightCount/2;
int rnd = end;
mergeSortWithBuffer(a, rls, rrs, rnd,tempBuffer);
}
mergeData(a, leftStart, rightStart, end, tempBuffer);
}
void mergeData(int *a, int leftStart, int rightStart, int end,int *tempBuffer) {
int leftCount = rightStart - leftStart;
int rightCount = end - rightStart + 1;
int lindex,rindex;
lindex = rindex = 0;
while (lindex < leftCount || rindex < rightCount) {
int lv = INT_MAX,rv = INT_MAX;
if (lindex < leftCount) { lv = a[leftStart + lindex]; }
if (rindex < rightCount) { rv = a[rightStart + rindex]; }
if (lv <= rv) {
tempBuffer[leftStart + lindex + rindex] = lv;
lindex ++;
}else {
tempBuffer[leftStart + lindex + rindex] = rv;
rindex ++;
}
}
for (int index = 0; index < end - leftStart + 1; index ++) {
a[leftStart + index] = tempBuffer[leftStart + index];
}
}
I thought the mergeData function can replace data in the point a each other without the temp buffer, but the logic is too complex and the efficient is not fast, so i add the temp buffer in this function.
Would you have better suggestions if you have willing?
How can I cycle through the array using a for loop and the reference operator?
for (i = 0; i < university->size; i++)
{
if (university->arr->MarkA <= 100)
{
sum += university->arr->MarkA;
count++;
}
Where should I insert the i?
These are the structures:
typedef struct Student
{
char *name;
long ID;
int MarkA, MarkB, HW;
}stud;
typedef struct University
{
stud *arr;
int size;
}Uni;
I used a function to create a University array
void build_Uni(FILE* in, Uni* university)
{
int i = 0;
stud temp;
char Name[100];
while (!feof(in))
{
fscanf(in, "%s%li%d%d%d", Name, &temp.ID, &temp.MarkA, &temp.MarkB, &temp.HW);
i++;
}
university->size = i;
rewind(in);
university->arr = (stud*)malloc(university->size * sizeof(stud));
if (university->arr == NULL) Get_Lost("Memory allocation failed!");
else for (i = 0; i < university->size; i++)
fill_Uni(in, university->arr + i);
}
void fill_Uni(FILE* in, stud* student)
{
char Name[100];
fscanf(in, "%s%li%d%d%d", Name, &student->ID, &student->MarkA, &student->MarkB, &student->HW);
student->name = (char*)malloc((strlen(Name) + 1) * sizeof(char));
if (student->name == NULL) Get_Lost("Error allocatig memory");
strcpy(student->name, Name);
}
In the main function I called the above functions to work on this structure
Uni university;
How can I cycle through the array using a for loop and the reference
operator?
I think you mean the dereference operator -> but referencing and dereferencing will have nothing to do with cycling through the array; that's what your for-loop is for.
Where should I insert the i?
This:
for (i = 0; i < university->size; i++)
{
if (university->arr->MarkA <= 100)
{
sum += university->arr->MarkA;
count++;
}
}
Should be this:
for (i = 0; i < university->size; i++)
{
if (university->arr[i].MarkA <= 100)
{
sum += university->arr[i].MarkA;
count++;
}
}
Concerning your original question, you should access it as follows:
University university;
...
for (i = 0; i < university.size; i++) {
if (university.arr[i].MarkA <= 100)
{
sum += university.arr[i].MarkA;
count++;
}
...
}
If university is of type University*, however, the code changes a little bit, since you then have to use operator -> to access the university-members:
for (i = 0; i < university->size; i++) {
if (university->arr[i].MarkA <= 100)
{
sum += university->arr[i].MarkA;
count++;
}
...
}
I want to append numbers to an empty array and the amount of these numbers is unknown at the start. For example, generating numbers from 1 to 10 and appending one after another.
generateFromOneToTen will save my result in output and count should be 10 after execution. Everything's alright if I print the result in this function.
int generateFromOneToTen(int *output, int count)
{
for (int i = 0; i < 10; i++) {
output = arrayAppendInt(output, i + 1, count);
count++;
}
// Print result of `output` is 1,2,3...10 here
return count;
}
And I implemented arrayAppendInt to dynamic increase the length of an array and append new value after the old ones.
int *arrayAppendInt(int *array, int value, int size)
{
int newSize = size + 1;
int *newArray = (int*) realloc(array, newSize * sizeof(int));
if (newArray == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
newArray[size] = value;
return newArray;
}
Here comes the question. When invoking the generation function, numbers will always be NULL. How can I return the generated numbers to the numbers variable?
int *numbers = NULL;
int count = 0;
count = generateFromOneToTen(numbers, 0);
^^^^^^^
You could use a pointer to a pointer of integer (int **):
int generateFromOneToTen(int **output, int count)
{
for (int i = 0; i < 10; i++) {
*output = arrayAppendInt(*output, i + 1, count);
count++;
}
// `*output` is 1,2,3...10 here
return count;
}
You could re-write the arrayAppendInt function like that:
int *arrayAppendInt(int *array, int value, int size)
{
int newSize = size + 1;
int *newArray;
if (array==NULL)
newArray = (int*) malloc ((1+size) * sizeof(int));
else
newArray = (int*) realloc(array, newSize * sizeof(int));
if (newArray == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
newArray[size] = value;
return newArray;
}
And call it like that *output = arrayAppendInt(*output, i + 1, i);.
The cleanest solution is (in my opinion) to pack the array+the bookkeeping (size,used) into a structure, and use (a pointer to) this structure as an argument.
#include <stdlib.h>
struct dopedarray {
unsigned size;
unsigned used;
int *array;
};
Now you can put all your allocation and bookkkeeping stuff into a single function (which can be inlined) :
int array_resize(struct dopedarray *ap, unsigned newsize)
{
int *newp;
if(!ap) return -1;
newp = realloc (ap->array, newsize*sizeof*ap->array);
// check return value here...
if (!newp) return -1;
free(ap->array);
ap->array = newp;
ap->size = newsize;
// bookkeeping sanity
if(ap->size > ap->used ) { ap->used > ap->size; }
return 0;
}
The add_element function needs to be changed a bit, too:
int array_add_element(struct dopedarray *ap, int value)
{
if(ap->used >= ap->size){
unsigned newsz;
newsz= ap->used ? 2*ap->used: 4;
array_resize(ap, newsz);
// check return value here...
}
ap->array[ap->used++] = val;
return 0;
}
The complete code to my question:
int generateFromOneToTen(int **output, int count) // +
{
for (int i = 0; i < 10; i++) {
*output = arrayAppendInt(*output, i + 1, count); // ++
count++;
}
return count;
}
int *arrayAppendInt(int *array, int value, int size)
{
int newSize = size + 1;
int *newArray = (int*) realloc(array, newSize * sizeof(int));
if (newArray == NULL) {
printf("ERROR: unable to realloc memory \n");
return NULL;
}
newArray[size] = value;
return newArray;
}
int *numbers = NULL;
int count = 0;
count = generateFromOneToTen(&numbers, 0); // +
This answer also worths reading: https://stackoverflow.com/a/9459803/1951254
I want to produce a random sequence of numbers between a range, for example 100 to 200.
After a while, depending on some events, I want to produce a new sequence between the same range (100 to 200), but this time I want to exclude some numbers. For example I don't want [150,165,170].
And the next time, these excluded numbers may or may not be included in the sequence.
One possible approach could be an array of numbers like this:
int rndm[] {100,101,102,103,...};
and use the index of the array to generate a random number at a time:
random(rndm[0-99]);
But I need to use as few instruction/data structures as possible in order to achieve performance.
I am using C for this code and I use random() or randomSeed(seed) and I want to know what the most efficient approach to handle this issue is, in terms of data structures should be used for the speed and memory.
This solution is efficient in the case that there are not many exclusions during the lifetime, once the exclusion function is quadratic.
There is a struct called RandomArray that holds a pointer to and array with size N. N is the desired size of the sequence. The time and space complexity is linear O(N) for the create function.
When an event happens it shall call the function excludeValue, with a time complexity of O(N) and space complexity of 1.
If it is desired to exclude a bunch of values, the function excludeValues (pay attention to s at the end) shall be called. In this case the complexity is O(N x K) and the space complexity is 1. K is the amount of values that shall be excluded.
#include <stdio.h>
#include <stdlib.h>
struct RandomArray {
int *pData;
size_t dataLen;
int excludedIdx;
};
struct RandomArray *excludeValue(struct RandomArray *pAr, int val) {
size_t i;
for (i = 0; i < pAr->excludedIdx; ++i) {
if (pAr->pData[i] == val) {
pAr->excludedIdx--;
int tmp = pAr->pData[i];
pAr->pData[i] = pAr->pData[pAr->excludedIdx];
pAr->pData[pAr->excludedIdx] = tmp;
// Do test again the position
--i;
}
} return pAr;
}
struct RandomArray *excludeValues(struct RandomArray *pAr, int *pVals, size_t len) {
size_t i;
for (i = 0; i < len; ++i)
excludeValue(pAr, pVals[i]);
}
struct RandomArray *destroyRandomArray(struct RandomArray *pAr) {
if (pAr) {
if (pAr->pData)
free(pAr->pData);
pAr->dataLen = 0;
}
return pAr;
}
struct RandomArray *createRandomArray(
struct RandomArray *pAr,
size_t dataLen,
int lowLimit, int highLimit) {
int i;
int range = (highLimit - lowLimit);
pAr->pData = (int*)malloc(sizeof(int) * dataLen);
pAr->dataLen = dataLen;
srand(time(NULL));
for (i = 0; i < dataLen; ++i) {
pAr->pData[i] = rand() % (range + 1) + lowLimit;
}
// Clear excluded indexs
pAr->excludedIdx = pAr->dataLen; return pAr;
}
void printRandomArray(struct RandomArray *pAr) {
size_t i;
printf("Random Array (len = %d): ", pAr->dataLen);
for (i =0; i < pAr->dataLen; ++i) {
printf(" %d", pAr->pData[i]);
}
printf("\n");
}
void printValidRandomArray(struct RandomArray *pAr) {
size_t i;
printf("Valid Random Array (len = %d): ", pAr->excludedIdx);
for (i =0; i < pAr->excludedIdx; ++i) {
printf(" %d", pAr->pData[i]);
}
printf("\n");
}
void printExcludedRandomArray(struct RandomArray *pAr) {
size_t i;
printf("Excluded Random Array (len = %d): ", pAr->dataLen - pAr->excludedIdx);
for (i = pAr->excludedIdx; i < pAr->dataLen; ++i) {
printf(" %d", pAr->pData[i]);
}
printf("\n");
}
void printAllRandomArray(struct RandomArray *pAr) {
printRandomArray(pAr);
printValidRandomArray(pAr);
printExcludedRandomArray(pAr);
}
int main() {
int lowLimit = 100;
int highLimit = 105;
int arrayLen = 10;
struct RandomArray myAr;
createRandomArray(&myAr, arrayLen, lowLimit, highLimit);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 100);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 101);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 102);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 103);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 104);
printAllRandomArray(&myAr);
printf("\n");
excludeValue(&myAr, 105);
printAllRandomArray(&myAr);
destroyRandomArray(&myAr);
createRandomArray(&myAr, arrayLen, lowLimit, highLimit);
printf("\n\n\n");
printAllRandomArray(&myAr);
printf("\n");
int vals[] = { 102, 105, 104 };
excludeValues(&myAr, vals, sizeof(vals) / sizeof(vals[0]));
printAllRandomArray(&myAr);
destroyRandomArray(&myAr);
}
This was asked here on the Arduino forum but I saw it here too. My answer is in Arduino's flavor of C++ since it was posted there...
Of course, performance varies as the set of excluded numbers grows relative to the set of numbers to be used to create your "new sequence."
void setup() {
Serial.begin(115200);
randomSeed(analogRead(A0));
}
void loop() {
// create an arbitray sized array to be filled with unique values to exclude from desired array
const int arraySize = 5;
int exclusions[arraySize];
for (int i = 0; i < arraySize; i++) {
// fill the array with unique values...
int val;
do {
val = random(100, 200);
} while([&]() {
for (auto j : exclusions) {
if (val == j) {
return true;
}
}
return false;
}());
exclusions[i] = val;
}
Serial.print(F("Exclusion Array: "));
for (int i = 0; i < arraySize; i++) {
Serial.print(exclusions[i]);
if (i < arraySize - 1)
Serial.print(F(", "));
}
Serial.println();
// create a new array of arbitrary length of unique random numbers in >>>the same<<< range as above (but not necessary)
Serial.print(F("Starting...\n"));
uint32_t start = millis();
const int listSize = 32;
int list[listSize];
for (int i = 0; i < listSize; i++) {
// fill the array with unique values that will exclude exclusions[]
int val;
do {
val = random(100, 200);
} while([&]() {
for (auto j : list) {
if (val == j) {
return true;
}
for (auto k : exclusions) {
if (val == k) {
return true;
}
}
}
return false;
}());
list[i] = val;
}
uint32_t end = millis();
Serial.println(end - start);
// OPTIONAL -> lets sort the final arry to make spotting the duplicates easier:
for (int i = 0; i < listSize; i++) {
for (int j = i + 1; j < listSize; j++) {
if (list[j] < list[i]) {
int temp = list[i];
list[i] = list[j];
list[j] = temp;
}
}
}
// output the final array
Serial.print(F("Final Array: "));
for (int i = 0; i < listSize; i++) {
Serial.print(list[i]);
if (i < listSize - 1)
Serial.print(F(", "));
}
Serial.print(F("\n\n\n"));
delay(1000);
}