Activity - Intersection of counters
-
Review set_iterate2. It shows how to construct the union of two sets.
-
Discuss how you would construct the intersection of two counters lists. The intersection is comprised of nodes that are present in both lists. If a node is present in both lists, for today (and Lab 6), define the count in the resulting intersection list to be the minimum of the counts of the two nodes. For a counters node with a key that does not exist in both sets, we set its count to 0 in the intersection result.
- Copy the starter code
intersect
to your cs50/ directory after logging to the plank server:$ cp -r $loc/activities/day22/intersect/ .
Here counters_intersect.c creates two dummy counters lists. Your task is to complete the
counters_intersect()
function to perform counters intersection. - Once you complete
counters_intersect()
, you can compile and run the code as below:$ mygcc -o intersect counters_intersect.c libcs50/libcs50-given.a $ ./intersect {3=2, 4=0, 5=1, 7=3, }
Hint: Make sure to use the
counters_iterate()
function. Below is a reminder of howcounters_iterate()
was implemented:
/**************** counters_iterate() ****************/
void
counters_iterate(counters_t *ctrs, void *arg,
void (*itemfunc)(void *arg, const int key, int count))
{
if (ctrs != NULL && itemfunc != NULL) {
// scan the counters
for (countersnode_t *node = ctrs->head; node != NULL; node = node->next) {
(*itemfunc)(arg, node->key, node->count);
}
}
}
You will need this for Lab 6’s AND operator!
Solution
Intersection is tricky (and inefficient!) with the functions available in the counters module. To accomplish an intersection of two counters, we need pseudocode like this:
result = counters_new()
for each (key,item) in c1
if key found in c2
add (key,item) to result
else
add (key, 0) to result
That second line is like calling counters_iterate(c1, ...)
, but then how does its helper function accomplish the contents of that loop?
It needs access to both c2
and result
.
Remember how a previous lecture passed two sets into an iterator and hence into the helper function?
We can do the same here; declare a small struct
to hold pointers to both result
and another
.
struct twocts { counters_t *result, *another } ; //store result in first counter
struct twocts args = { c1, c2 };
counters_iterate(c1, &args, intersect_helper);
The pointer to args
will pass through counters_iterate
and be available to intersect_helper
and thus that function can implement remainder of our pseudocode above.