CS302 Midterm Exam - October 17, 2023

The exam was given online using Canvas. I used banks for several questions, so this is more of an example exam than the actual exam. When I give answers, they are to these questions. Questions 1 through 15 were from a bank -- whatever questions you were asked will map well to these 15 questions -- you can typically use the name of the procedure (e.g. "proc_1e961()") to map to the question here.

Questions 1-15 were worth 2 points each.


Question 1

/* In this snippet of code, we are using an implementation of disjoint sets
   that employs Union by Rank with Path Compression.  V's size is n.

   disjoint_set.hpp contains the following definition:

namespace plank {

class Disjoint_Set {
  public:
    void Initialize(int num_elements);
    int Union(int s1, int s2);             // s1 and s2 are set id's, not elements.
                                           // Union() returns the set id of the new union.
    int Find(int element);                 // return the set id of the element.
    size_t Size() const;
    ...                                    // Other stuff.
}

}

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include "disjoint_set.hpp"
using namespace std;
using plank::Disjoint_Set;

Disjoint_Set *proc_1e961(vector <bool> &v, int &m)
{
  Disjoint_Set *d;
  size_t i;

  d = new Disjoint_Set;
  d->Initialize(v.size());
  for (i = 1; i < v.size(); i++) {
    if (v[i]) d->Union(d->Find(0), i);
  }
  m = 0;
  for (i = 0; i < d->Size(); i++) {
    if (d->Find(0) == d->Find(i)) m++;
  }
  return d;
}


Question 2

/* When we execute this snippet of code, e's size is zero, 
   b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_cc0ad(map<int, int> &e, const vector <int> &b)
{ 
  size_t j;

  for (j = 0; j < b.size(); j++) {
    e.insert(make_pair(j, b[j]));
  }
}


Question 3

/* When we execute this snippet of code: 

   - f's size is 0
   - z's size is 0
   - v's size is n
   - b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <unordered_map>
using namespace std;

void proc_592f7(unordered_map<int, int> &f, vector <int> &z, vector <int> &v, vector <int> &b)
{
  unordered_map <int, int>::iterator oit;
  size_t i;
  
  for (i = 0; i < v.size(); i++) {
    f.insert(make_pair(b[i], v[i]));
  }
  
  for (oit = f.begin(); oit != f.end(); oit++) {
    z.push_back(oit->second);
  }
}


Question 4

/* When we execute this snippet of code, e's size is zero, 
   b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_6bb2e(map<int, int> &e, const vector <int> &b)
{
  size_t i;

  for (i = 0; i < b.size(); i++) {
    e.insert(make_pair(b[i], i));
  }
}


Question 5

/* When we execute this snippet of code, d's size is n,

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <deque>
using namespace std;

int proc_b3229(deque<int> &d)
{
  deque <int>::iterator dit, eit;
  int matches;
  
  matches = 0;
  for (dit = d.begin(); dit != d.end(); dit++) {
    eit = dit;
    for (eit++; eit != d.end(); eit++) {
      if (*eit == *dit) matches++;
    }
  }
  return matches;
}


Question 6

/* When we execute this snippet of code, em's size is zero, 
   b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_a9e99(multimap<int, int> &em, const vector <int> &b)
{
  size_t k;

  for (k = 0; k < b.size(); k++) {
    em.insert(make_pair(b[k], k));
  }
}


Question 7

/* When we execute this snippet of code, x's size is m and v's size is n.

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_9c940(const map<int, int> &x, vector <int> &v)
{
  map <int, int>::const_iterator mit;

  for (mit = x.begin(); mit != x.end(); mit++) {
    v.push_back(mit->first);
    v.push_back(mit->second);
  }
}


Question 8

/* When we execute this snippet of code, x's size is m, z's size is 0, and v's size is n.

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_6db03(map<int, int> &x, vector <int> &z, vector <int> &v)
{
  map <int, int>::iterator bit;
  size_t i;
  int j;
  
  for (i = 0; i < v.size(); i++) {
    for (bit = x.begin(); bit != x.end() && bit->first < v[i]; bit++) ;
    if (bit == x.end()) {
      j = 0;                         // Case 0, v[i] is bigger than everything in x
    } else if (bit->first > v[i]) {
      j = 1;                         // Case 1, v[i] is not in x
    } else {                        
      j = 2;                         // Case 2, v[i] is in x
    }
    z.push_back(j);
  }
}


Question 9

/* In this snippet of code, we are using an implementation of disjoint sets
   that employs Union by Rank with Path Compression.  V's size is n.

   disjoint_set.hpp contains the following definition:

namespace plank {

class Disjoint_Set {
  public:
    void Initialize(int num_elements);
    int Union(int s1, int s2);             // s1 and s2 are set id's, not elements.
                                           // Union() returns the set id of the new union.
    int Find(int element);                 // return the set id of the element.
    ...                                    // Other stuff.
}

}
   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include "disjoint_set.hpp"
using namespace std;
using plank::Disjoint_Set;

Disjoint_Set *proc_8eaf7(vector <bool> &v)
{
  Disjoint_Set *d;
  size_t i;

  d = new Disjoint_Set;
  d->Initialize(v.size());
  for (i = 1; i < v.size(); i++) {
    if (v[i]) d->Union(d->Find(0), i);
  }
  return d;
}


Question 10

/* When we execute this snippet of code, x's size is m, and z's size is 0.

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_a018f(map<int, int> &x, vector <int> &z)
{
  map <int, int>::iterator nit;

  for (nit = x.begin(); nit != x.end(); nit++) {
    z.push_back(x[nit->first]);
  }
}


Question 11

/* When we execute this snippet of code, d's size is m,
   b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <deque>
using namespace std;

void proc_b3229(deque<int> &d, const vector <int> &b)
{
  int c;

  for (c = 0; c < b.size(); c++) {
    if (c % 2 == 0) {
      d.push_back(b[c]);
    } else {
      d.push_front(b[c]);
    }
  }
}


Question 12

/* In this snippet of code, we are using an implementation of disjoint sets
   that employs Union by Rank with Path Compression.  D->Size equals n.

   disjoint_set.hpp contains the following definition:

namespace plank {

class Disjoint_Set {
  public:
    void Initialize(int num_elements);
    int Union(int s1, int s2);             // s1 and s2 are set id's, not elements.
                                           // Union() returns the set id of the new union.
    int Find(int element);                 // return the set id of the element.
    size_t Size() const;
    ...                                    // Other stuff.
}
}

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include "disjoint_set.hpp"
using namespace std;
using plank::Disjoint_Set;

int proc_7d81c(Disjoint_Set &d)
{
  size_t i;
  int m;

  m = 0;
  for (i = 1; i < d.Size(); i++) {
    if (d.Find(0) == d.Find(i)) m++;
  }
  return m;
}


Question 13

/* When we execute this snippet of code, f's size is zero, 
   b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <unordered_map>
using namespace std;

void proc_5eca9(unordered_map<int, int> &f, const vector <int> &b)
{
  size_t l;

  for (l = 0; l < b.size(); l++) {
    f.insert(make_pair(l, b[l]));
  }
}


Question 14

/* When we execute this snippet of code, x's size is m,
   b's size is n, and all of the elements of b are between 0 and 5. 

   What is the big-O expression for the running time of this procedure? */

#include <vector>
#include <map>
using namespace std;

void proc_28066(map<int, int> &x, const vector <int> &b)
{
  size_t a;

  for (a = 0; a < b.size(); a++) {
    x.insert(make_pair(b[a], a));
  }
}


Question 15

/* When we execute this snippet of code, v's size is n.

   What is the big-O expression for the running time of this procedure? */

#include <vector>
using namespace std;

void proc_da9ac(vector <int> &v)
{
  int g, i, s;
  
  s = 0;
  for (g = 0; g < (1 << v.size()); g++) {
    for (i = 0; i < v.size(); i++) {
      if (g & (1 << i)) s = s ^ v[i];
    }
  }
}


Question 16 -- 15 points

Please answer each of the following. Don't calculate it out to be a number, but simply give an expression. Use the carat (^) for exponentiation, exclamation point (!) for factorial, and C(n,k) for n-choose-k.

Part A: You force each of your employees to choose a password composed of exactly 5 lower-case letters followed by 4 single numeric digits. How many potential passwords are there?

Part B: You are running a lottery. You have a machine with 17 ping-pong balls, numbered 1 to 17. It has been programed to choose one of these balls at random every second. Each time a ball is chosen, it is put back onto the machine, so your machine always has the same 17 balls. Your lottery number is composed of the ping-pong ball numbers chosen in the last 6 seconds, ordered from most recently-chosen to least recently-chosen. How many different lottery numbers are there?

Part C: You are buying a new home. In your old home, you had 17 different TV's. Your new home only has room for 12 TV's, so you have to donate 5 of them to charity. How many different ways are there for you to donate those 5 TV's to charity?

Part D: There is a skyscraper in New York City whose spire has 11 lights arranged vertically. You can put a gel over a light, and that makes it a specific color. You have 11 different-colored gels. Each night, you'll use all of the gels, but you want to make sure that the gels form a different arrangement of colors every night. How many nights can you go without ever repeating an arrangement?

Part E: I'm having breakfast at a bed-and-breakfast, and my host asks me what kind of juice I want. Instead of just saying "Orange", I was dumb enough to ask what she had. She said, "I have 12 kinds of juice. You can have any of them on their own, or you can combine any of them that you want in equal quantities. Or you can skip juice altogether! See, there are infinite combinations!!" You're too polite to tell her that she's wrong. How many combinations are there? (I hate to say that this is a true story, but it is):


Question 17: 15 points

Suppose we have three classes, A, B and C. In scenario 1, A is an interface for B and C. In scenario 2, A is a super-class for B and C in which inheritance is employed.

Please explain, in your own words, how scenario 2 differs from scenario 1. In your explanation, I want you to demonstrate to me that you know what interfaces are, and what inheritance is.

Then, please explain how scenario 2 can be a problem over the lifetime of a long software project.


Question 18: 7 points

Given the following class definition of disjoint sets:

class DisjointSetByRankWPC : public DisjointSet {
  public:
    DisjointSetByRankWPC(int nelements);
    int Union(int s1, int s2);
    int Find(int element);
    void Print() const;

  protected:
    std::vector <int> links;
    std::vector <int> ranks;
};

Please implement Find(). In case it's not clear, the implementation is Union by Rank with Path Compression.


Question 19: 8 points

Please implement the following procedure:
unsigned int reverse(unsigned int v);

This procedure should return a value that contains the bits of v in reverse order.

For example, if v is 0x8100000c, then reverse(v) should return 0x30000081.


Question 19: 15 points

Please write the following procedure:

double zero(const vector < vector <double> > &v);

The vector v contains (x,y) points of a piecewise linear function. The x values are guaranteed to be increasing and the y values are guaranteed to be decreasing. Moreover, v[0][0] is guaranteed to be less than zero, and v[v.size()-1][0] is guaranteed to be greater than zero.

Return the y value that corresponds to an x value of zero.

BTW, if you have two points (x1, y1) and (x2, y2) that define a linear function, then the y value that corresponds to an x value of zero is given by the following:

y = y1 - (x1 * (y2-y1) / (x2-x1)).

You may not use any procedures from the C++ algorithms library, and the only vector methods that you may use are size() and at().

Example 0: v = [ [-1,1], [1,0] ]                      -- Answer = 0.5
Example 1: v = [ [-100,499], [-2,5], [1,2], [450,0] ] -- Answer = 3

Your solution needs to implement the appropriate algorithm for this task.

Remember -- setting your input box to "preformatted" gives you a nice fixed-width font. You may also resize that box to make it bigger, which can be helpful.