TEST(Test04, MembershipTests) { { int x[100]; Set universal; createEmptySet(&universal); for (int i = 0; i < 100; i++) { insertSet(&universal, i); x[i] = i; } Set s; createCopySet(&s, &universal); for (int i = 0; i < 50; i++) { /* choose a random element in array x */ int k = rand() % (100 - i); int val = x[i]; /* remove that random value from x by copying the last element into position k */ x[k] = x[100 - i - 1]; ASSERT_TRUE(isMemberSet(&s, val)); removeSet(&s, val); ASSERT_FALSE(isMemberSet(&s, val)); } } }
/* * don't forget: it is OK to try to remove an element * that is NOT in the set. * If 'x' is not in the set 'self', then * removeSet should do nothing (it's not an error) * Otherwise, ('x' IS in the set), remove x. Be sure to update self->length * It is not necessary (nor recommended) to call malloc -- if removing an element means the * array on the heap is "too big", that's almost certainly OK, and reallocating a smaller array * is almost definitely NOT worth the trouble * * My notes: if the set is empty, don't do anything because it's impossible to remove from a * set with no members in it. If set is singleton, quicker to just do it manually. * * param self: set to remove element 'x,' assuming 'x' is in the set. * param x: member to remove from set 'self' * return: N/A */ void removeSet(Set* self, int x) { if ((!isMemberSet(self, x)) || (isEmptySet(self)) || (!isSorted(self))) { return; } if (self->len == 1) { /* easier to manually remove for a singleton set */ self->elements[0] = 0; self->len = 0; return; } int deleteHere = 0; for (int index = 0; index < self->len; index++) { /* determine index where 'x' is within set */ if (self->elements[index] == x) { deleteHere = index; } } for (int index = deleteHere; index < self->len; index++) { /* O(N). */ if (index != (self->len - 1)) { /* don't want to write potentially random value to last member spot */ self->elements[index] = self->elements[index + 1]; /* shift every member to left one to update set members */ } else { self->elements[index] = 0; /* index reached last member spot. Make as empty spot */ } } self->len = self->len - 1; /* update length of set */ }
void isMemberTimeFun(void) { if (isMemberSet(setA, is_mem_x)) { is_mem_x ^= 1; is_mem_x <<= 1; } else { is_mem_x >>= 1; is_mem_x ^= 2; } }
/** * add x as a new member to this set. * If x is already a member, then self should not be changed * Be sure to restore the design invariant property that elemnts[] remains sorted * (yes, you can assume it is sorted when the function is called, that's what an invariant is all about). * * My notes: if the self 'self' isn't sorted, do nothing because you have an invalid input. * If the set is empty, create large memory on heap so you don't have to worry about reallocation * or changing number of members in set. Update length of set 'self.' * * param self: set that will have 'x' inserted into it. * param x: member to insert into 'self,' assuming it is not already in 'self' and 'self' is sorted. * return: N/A */ void insertSet(Set* self, int x) { if (isMemberSet(self, x) || (!isSorted(self))) { /* Don't insert element 'x' if 'x' is already in set */ return; } self->elements = (int*) realloc(self->elements, (self->len * sizeof(int)) + sizeof(int)); /* allocate the same amount of memory on heap + 1 */ int index = 0; for (index = 0; index < self->len; index++) { if (self->elements[index] > x) { /* correct index found for new member 'x.' */ for (int shiftIndex = self->len; shiftIndex > index; shiftIndex--) { /* start at the new largest index (+1 of the previous largest index) */ self->elements[shiftIndex] = self->elements[shiftIndex - 1]; /* shift the members to the right one */ } break; /* exits the nearest while loop (i.e. the outermost loop here */ } } self->elements[index] = x; /* 'index' value holds index where 'x' should be inserted */ self->len = self->len + 1; /* update length of set 'self' */ }
/* * create two sets with n random elements * the sets should have 50% of the elements in common */ void createRandomSetN(int n, Set* a, Set* b) { int x; int last_size = 0; createEmptySet(a); while (a->len < n) { if (a->len != last_size) { last_size = a->len; if (last_size % 1000 == 0) { printf("%d..", last_size); fflush(stdout); } } x = 2 * (5 * n - (rand() % (10 * n))); if (isMemberSet(a, x)) { continue; } // try another number /* a will have only even elements */ insertSet(a, x); if ((rand() % 2) == 0) { insertSet(b, x); } else { insertSet(b, x + 1); // an odd value, can't be in a } } assert(a->len == b->len); }
void specialCaseTests(void) { Set empty; Set universal; int i; Set s; Set r; createEmptySet(&empty); createEmptySet(&universal); createEmptySet(&r); for (i = 0; i < maximum_set_size; i += 1) { insertSet(&universal, i); } checkCase(&subtractFromSet, &universal, &universal, &empty); checkCase(&unionInSet, &universal, &universal, &universal); checkCase(&intersectFromSet, &universal, &universal, &universal); checkCase(&intersectFromSet, &universal, &empty, &empty); checkCase(&intersectFromSet, &empty, &universal, &empty); checkCase(&unionInSet, &universal, &empty, &universal); checkCase(&unionInSet, &empty, &universal, &universal); checkCase(&unionInSet, &empty, &empty, &empty); checkCase(&subtractFromSet, &empty, &empty, &empty); checkCase(&intersectFromSet, &empty, &empty, &empty); createEmptySet(&s); assert(isEmptySet(&s)); for (i = 0; i < 10; i += 1) { insertSet(&s, i); } assert(s.len == 10); for (i = 0; i < 10; i += 1) { assert(isMemberSet(&s, i)); } for (i = 0; i < 10; i += 1) { removeSet(&s, i); removeSet(&s, i); assert(s.len == 9 - i); } assert(isEmptySet(&s)); for (i = 0; i < number_of_tests; i += 1) { randomSet(&s); assert(isSubsetOf(&empty, &s)); assert(!isSubsetOf(&s, &empty)); assert(isSubsetOf(&s, &universal)); assert(!isSubsetOf(&universal, &s)); checkCase(&intersectFromSet, &empty, &s, &empty); checkCase(&intersectFromSet, &s, &empty, &empty); checkCase(&intersectFromSet, &universal, &s, &s); checkCase(&intersectFromSet, &s, &universal, &s); checkCase(&unionInSet, &universal, &s, &universal); checkCase(&unionInSet, &s, &universal, &universal); checkCase(&subtractFromSet, &s, &empty, &s); assignSet(&r, &universal); subtractFromSet(&r, &s); // r = u - s; checkCase(&subtractFromSet, &universal, &r, &s); // (u - (u - s) == s) checkCase(&unionInSet, &s, &r, &universal); // s + (u - s) == u checkCase(&unionInSet, &r, &s, &universal); // (u - s) + s == u } printf("The special case tests have been passed\n"); destroySet(&empty); destroySet(&universal); destroySet(&s); destroySet(&r); }
TEST(Test05, SpecialCaseTests) { { Set empty; Set universal; Set s; Set r; int i; createEmptySet(&empty); createEmptySet(&universal); createEmptySet(&r); for (i = 0; i < MAX_SET_SIZE; i++) { insertSet(&universal, i); } ASSERT_TRUE(checkCaseNew(&subtractFromSet, &universal, &universal, &empty)); ASSERT_TRUE(checkCaseNew(&unionInSet, &universal, &universal, &universal)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &universal, &universal, &universal)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &universal, &empty, &empty)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &empty, &universal, &empty)); ASSERT_TRUE(checkCaseNew(&unionInSet, &universal, &empty, &universal)); ASSERT_TRUE(checkCaseNew(&unionInSet, &empty, &universal, &universal)); ASSERT_TRUE(checkCaseNew(&unionInSet, &empty, &empty, &empty)); ASSERT_TRUE(checkCaseNew(&subtractFromSet, &empty, &empty, &empty)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &empty, &empty, &empty)); createEmptySet(&s); ASSERT_TRUE(isEmptySet(&s)); for (i = 0; i < 10; i++) { insertSet(&s, i); } ASSERT_TRUE(s.len == 10); for (i = 0; i < 10; i++) { ASSERT_TRUE(isMemberSet(&s, i)); } for (i = 0; i < 10; i++) { removeSet(&s, i); removeSet(&s, i); ASSERT_TRUE(s.len == 9 - i); } ASSERT_TRUE(isEmptySet(&s)); for (i = 0; i < NUM_TESTS; i++) { randomSet(&s); ASSERT_TRUE(isSubsetOf(&empty, &s)); ASSERT_FALSE(isSubsetOf(&s, &empty)); ASSERT_TRUE(isSubsetOf(&s, &universal)); ASSERT_FALSE(isSubsetOf(&universal, &s)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &empty, &s, &empty)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &s, &empty, &empty)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &universal, &s, &s)); ASSERT_TRUE(checkCaseNew(&intersectFromSet, &s, &universal, &s)); ASSERT_TRUE(checkCaseNew(&unionInSet, &universal, &s, &universal)); ASSERT_TRUE(checkCaseNew(&unionInSet, &s, &universal, &universal)); ASSERT_TRUE(checkCaseNew(&subtractFromSet, &s, &empty, &s)); assignSet(&r, &universal); subtractFromSet(&r, &s); ASSERT_TRUE(checkCaseNew(&subtractFromSet, &universal, &r, &s)); ASSERT_TRUE(checkCaseNew(&unionInSet, &s, &r, &universal)); ASSERT_TRUE(checkCaseNew(&unionInSet, &r, &s, &universal)); } destroySet(&empty); destroySet(&universal); destroySet(&s); destroySet(&r); } }