/* add all elements of other to self (obviously, without creating duplicate elements) */ void unionInSet(Set* self, const Set* other) { if (isEmptySet(other)) { return; } //adding nothing to self set if (isEqualToSet (self, other)) { return; } //same set, nothing to add if (isSubsetOf (other, self)) { return; } //everything in other already in self if (self == other) { return; } //same set, nothing to add if (self->len == 0) { createCopySet (self, other); } else { Set copy_set; createCopySet (©_set, self); copy_set.capacity = copy_set.len + other->len; destroySet (self); self->elements = (int*) malloc (copy_set.capacity * sizeof (int)); //self now has room to union two unique sets int copy_index = 0; int other_index = 0; int self_index = 0; while (copy_index < copy_set.len || other_index < other->len) { if (copy_set.elements[copy_index] == other->elements[other_index]) { self->elements[self_index] = copy_set.elements[copy_index]; other_index += 1; copy_index += 1; } else if ((other_index >= other->len || copy_set.elements[copy_index] < other->elements[other_index]) && copy_index < copy_set.len) { self->elements[self_index] = copy_set.elements[copy_index]; copy_index += 1; } else if ((copy_index >= copy_set.len || copy_set.elements[copy_index] > other->elements[other_index]) && other_index < other->len) { self->elements[self_index] = other->elements[other_index]; other_index += 1; } self_index += 1; } self->len = self_index; self->capacity = copy_set.capacity; destroySet (©_set); } //might have to recreate insert code/subset code here /*code here*/ //have two sets (one a copy of self), depending on which number is lower of the two sets at their respective indicies, put that one first into self //assert (checkValidSet (self)); //test code, remove later }
TEST(Test02, EqualityTests) { { for (int i = 0; i < NUM_TESTS; i++) { Set s; Set t; createEmptySet(&s); randomSet(&s); createCopySet(&t, &s); ASSERT_TRUE(isEqualToSet(&t, &s)); ASSERT_TRUE(isEqualToSet(&s, &t)); insertSet(&t, MAX_SET_SIZE); ASSERT_FALSE(isEqualToSet(&s, &t)); ASSERT_FALSE(isEqualToSet(&t, &s)); randomSet(&t); ASSERT_FALSE(isEqualToSet(&t, &s)); destroySet(&s); destroySet(&t); } } }
void checkCase(setFun fun, Set* s1, Set* s2, Set* expect) { Set res; createCopySet(&res, s1); (*fun)(&res, s2); assert(isEqualToSet(&res, expect)); destroySet(&res); }
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 */ void removeSet(Set* self, int x) { if (self->len == 0) { return; } //can not remove anything to empty set Set copy_set; createCopySet (©_set, self); destroySet (self); self->elements = (int*) malloc (copy_set.capacity * sizeof (int)); //recreate self with same capacity /*code here*/ int self_index = 0; int copy_index = 0; while (copy_index < copy_set.len) { if (x != copy_set.elements[copy_index]) { self->elements[self_index] = copy_set.elements[copy_index]; self_index += 1; } copy_index += 1; } self->len = self_index; self->capacity = copy_set.capacity; destroySet (©_set); //assert (checkValidSet (self)); //test code, remove later return; }
void visualTests() { Set s; Set t; int i; createEmptySet(&s); showOutput("The set constructed with the default constructor: ", &s); for (i = 0; i < 10; i += 1) { insertSet(&s, i); } showOutput("The set should be {0, ..., 9}: ", &s); // test Insert() and Contains() with '<<' for (i = 0; i < 10; i += 1) { insertSet(&s, i); } showOutput("The set should be {0, ..., 9}: ", &s); createCopySet(&t, &s); showOutput("The copy of s constructed with the copy constructor = ", &t); randomSet(&t); showOutput("The random set generated equals = ", &t); printf("The visual tests are over\n"); destroySet(&s); destroySet(&t); }
/** * Same thing as createCopySet, but the old int array pointed to by elements is freed. Don't do * anything if the sets are already equal (quicker). * * param self: pointer to a struct 'self' that will have an int member that points to the members * of the malloc'ed set. Old set is overwrited by the set pointer to by 'other,' assuming that the * sets aren't already equal. * param other: pointer to self 'other' that will have an int member that points to the members of * the malloc'ed set. The members of this struct will be copied to the int array in 'self.' * return: N/A */ void assignSet(Set* self, const Set* other) { if (self == other) { /* 'self' is already 'other' */ return; } destroySet(self); /* free pointer to old set in 'self' */ createCopySet(self, other); /* overwrite 'self' with 'other' */ }
bool checkCaseNew(setFun fun, Set *s1, Set *s2, Set *expect) { Set res; createCopySet(&res, s1); (*fun)(&res, s2); bool test_result = isEqualToSet(&res, expect); destroySet(&res); return test_result; }
/* * 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) */ void insertSet(Set* self, int x) { if (self->elements == 0) { //given empty set case createSingletonSet (self, x); return; } Set copy_set; createCopySet (©_set, self); copy_set.capacity += 1; //copy set with one more capacity destroySet (self); self->elements = (int*) malloc (copy_set.capacity * sizeof (int)); //recreate self with larger capacity if (x < copy_set.elements[0]) { //if x is inserted at beginning self->elements[0] = x; for (int i = 0; i < copy_set.len; i += 1) { self->elements[i + 1] = copy_set.elements[i]; } self->len += 1; } else if (x > copy_set.elements[copy_set.len - 1]) { //if x is inserted at end for (int k = 0; k < copy_set.len; k += 1) { self->elements[k] = copy_set.elements[k]; } self->elements[self->len] = x; self->len += 1; } else { //if x is inserted in middle int copy_index = 0; int self_index = 0; while (copy_index < copy_set.len) { self->elements[self_index] = copy_set.elements[copy_index]; if (x < self->elements[self_index] && x > self->elements[self_index - 1]) { self->elements[self_index] = x; } else { copy_index += 1; } self_index += 1; } self->len = self_index; } self->capacity = copy_set.capacity; destroySet (©_set); //assert (checkValidSet (self)); //test code, remove later return; }
void testTime(void) { Scales behavior[NUM_TESTS]; int k; int x; for (k = 0; k < num_times; k += 1) { printf("creating a random set with %d elements...", sizes[k]); fflush(stdout); createRandomSetN(sizes[k], &setsA[k], &setsB[k]); x = 10 * sizes[k]; createCopySet(&setsAPrime[k], &setsA[k]); insertSet(&setsA[k], x); insertSet(&setsAPrime[k], x + 1); insertSet(&setsB[k], x); printf("done\n"); } printf("checking scaling of isMember\n"); behavior[IS_MEMBER] = determineScaling(&isMemberTimeFun); printf("isMember's scaling appears to be: %s\n", scaling_strings[behavior[IS_MEMBER]]); printf("checking scaling of isEqualTo\n"); behavior[IS_EQUAL_TO] = determineScaling(&isEqualTimeFun); printf("isEqualTo's scaling appears to be: %s\n", scaling_strings[behavior[IS_EQUAL_TO]]); printf("checking scaling of isSubsetOf\n"); behavior[IS_SUBSET_OF] = determineScaling(&isSubsetTimeFun); printf("isSubsetOf's scaling appears to be: %s\n", scaling_strings[behavior[IS_SUBSET_OF]]); printf("checking scaling of unionIn\n"); behavior[UNION_IN] = determineScaling(&unionTimeFun); printf("unionIn's scaling appears to be: %s\n", scaling_strings[behavior[UNION_IN]]); printf("checking scaling of intersectFrom\n"); behavior[INTERSECT_FROM] = determineScaling(&intersectTimeFun); printf("intersectFrom's scaling appears to be: %s\n", scaling_strings[behavior[INTERSECT_FROM]]); printf("checking scaling of subtractFrom\n"); behavior[SUBTRACT_FROM] = determineScaling(&subtractTimeFun); printf("subtractFrom's scaling appears to be: %s\n", scaling_strings[behavior[SUBTRACT_FROM]]); printf("Performance Summary:\n"); printf("isMemberSet\t\t%s\n", scaling_strings[behavior[IS_MEMBER]]); printf("isEqualToSet\t\t%s\n", scaling_strings[behavior[IS_EQUAL_TO]]); printf("isSubsetOf\t\t%s\n", scaling_strings[behavior[IS_SUBSET_OF]]); printf("unionInSet\t\t%s\n", scaling_strings[behavior[UNION_IN]]); printf("intersectFromSet\t%s\n", scaling_strings[behavior[INTERSECT_FROM]]); printf("subtractFromSet\t\t%s\n", scaling_strings[behavior[SUBTRACT_FROM]]); }
/* * The structure of the output is: * * {} <default constructed set> * {0,1,...,9} <insert 0-9> * {0,1,...,9} <insert 0-9 (fail b/c repeat)> * {0,1,...,9} <copy constructed> * {0,2,3,...,95,99} <random set> */ TEST(Test01, VisualTests) { { std::set<int> basic, random; Set s; Set t; int i; createEmptySet(&s); assertSetsAreEqual(basic, &s); for (i = 0; i < 10; i++) { insertSet(&s, i); basic.insert(i); } assertSetsAreEqual(basic, &s); for (i = 0; i < 10; i++) { insertSet(&s, i); } assertSetsAreEqual(basic, &s); createCopySet(&t, &s); assertSetsAreEqual(basic, &t); Set temp; int n = rand() % MAX_SET_SIZE + 1; createEmptySet(&temp); for (int i = 0; i < n; i++) { int val = rand() % MAX_SET_SIZE; insertSet(&temp, val); random.insert(val); } reassignSet(&t, &temp); destroySet(&temp); assertSetsAreEqual(random, &t); destroySet(&s); destroySet(&t); } }
void equalityTests(void) { int i; for (i = 0; i < number_of_tests; i += 1) { Set s; Set t; createEmptySet(&s); randomSet(&s); createCopySet(&t, &s); assert(isEqualToSet(&t, &s)); assert(isEqualToSet(&s, &t)); insertSet(&t, maximum_set_size); assert(! isEqualToSet(&s, &t)); assert(! isEqualToSet(&t, &s)); randomSet(&t); assert(! isEqualToSet(&t, &s)); destroySet(&s); destroySet(&t); } // This test could fail with small probability printf("The equality tests have been passed\n"); }
/* remove all elements from self that are not also elements of other */ void intersectFromSet(Set* self, const Set* other) { if (isEmptySet(self)) { return; } //can't remove anything from empty set if (isEqualToSet (self, other)) { return; } //all elements aready in common if (isSubsetOf (self, other)) { return; } //everything in self is in other, nothing to remove if (self == other) { return; } //all elements already in common /*code here*/ //have two sets (one a copy of self), if they don't match increase other index until they do, if they match add to self and increase both indicies //might have to recreate remove code/subset code here Set copy_set; createCopySet (©_set, self); copy_set.capacity = copy_set.len; destroySet (self); self->elements = (int*) malloc (copy_set.capacity * sizeof (int)); //copy original set into copy_set and rebuild self int copy_index = 0; int other_index = 0; int self_index = 0; while (copy_index < copy_set.len && other_index < other->len) { if (copy_set.elements[copy_index] < other->elements[other_index]) { copy_index += 1; } else if (copy_set.elements[copy_index] > other->elements[other_index]) { other_index += 1; } else if (copy_set.elements[copy_index] == other->elements[other_index]) { self->elements[self_index] = copy_set.elements[copy_index]; self_index += 1; copy_index += 1; other_index += 1; } } self->len = self_index; self->capacity = copy_set.capacity; destroySet (©_set); //assert (checkValidSet (self)); //test code, remove later }
/* done for you already */ void assignSet(Set* self, const Set* other) { if (self == other) { return; } destroySet(self); createCopySet(self, other); }
void unionTimeFun(void) { Set t; createCopySet(&t, setA); unionInSet(&t, setB); destroySet(&t); }
/* remove all elements from self that are also elements of other */ void subtractFromSet(Set* self, const Set* other) { if (isEmptySet(self)) { return; } //can't remove anything from empty set if (isEmptySet(other)) { return; } //nothing to remove from self if (isSubsetOf (self, other)) { createEmptySet (self); return; } /*code here*/ //have two sets (one a copy of self), //might have to recreate remove code/subset code here /*Set intersect_set; createCopySet (&intersect_set, self); intersect_set.capacity = intersect_set.len; intersectFromSet (&intersect_set, other); //create temporary set with intersection of self and other */ Set copy_set; createCopySet (©_set, self); copy_set.capacity = copy_set.len; destroySet (self); self->elements = (int*) malloc (copy_set.capacity * sizeof (int)); //copy original set into copy_set and rebuild self /*int intersect_index = 0; int self_index = 0; int copy_index = 0; while (copy_index < copy_set.len) { if (copy_set.elements[copy_index] == intersect_set.elements[intersect_index]) { intersect_index += 1; copy_index += 1; } else if (intersect_index >= intersect_set.len || copy_set.elements[copy_index] < intersect_set.elements[intersect_index]) { self->elements[self_index] = copy_set.elements[copy_index]; copy_index += 1; self_index += 1; } else if (copy_set.elements[copy_index] > intersect_set.elements[intersect_index]) { intersect_index += 1; } }*/ int copy_index = 0; int self_index = 0; int other_index = 0; while (copy_index < copy_set.len) { if (other_index >= other->len || copy_set.elements[copy_index] < other->elements[other_index]) { self->elements[self_index] = copy_set.elements[copy_index]; self_index += 1; copy_index += 1; } else if (copy_set.elements[copy_index] > other->elements[other_index]) { other_index += 1; } else { copy_index += 1; other_index += 1; } } self->len = self_index; self->capacity = copy_set.capacity; destroySet (©_set); /*destroySet (&intersect_set);*/ //assert (checkValidSet (self)); //test code, remove later }
void subtractTimeFun(void) { Set t; createCopySet(&t, setA); subtractFromSet(&t, setB); destroySet(&t); }
void intersectTimeFun(void) { Set t; createCopySet(&t, setA); intersectFromSet(&t, setB); destroySet(&t); }