CS302 Midterm Exam: October 16, 2008 -- Answers & Grading

Question 1 - Five Points

The problem is that when you call this, the procedure will make a copy of the vector, set all of its elements to zero, and then throw it away. In other words, it doesn't do anything. For example, look at q1.cpp:

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

void clear_vector(vector <double> v)
  int i;

  for (i = 0; i < v.size(); i++) v[i] = 0;

  vector <double> a;

  cout << a[0] << endl;

When you run it, it prints one, because clear_vector() doesn't do anything:

UNIX> q1
To fix this, make v a pointer to a vector:

void clear_vector(vector <double> *v)

Or worse, make it a reference parameter:

void clear_vector(vector <double> &v)


Getting the right answer - 3 points. Getting the right solution - 2 points.

Question 2 - Five Points

There are five variables -- three (char *)'s and three C++ strings. Before we execute any code, s2 is pointing to the string "Wilma" and the others point to nothing:

Now, the line "st1 = s2" makes a copy of "Wilma", and the line "st2 = st1" makes another copy of "Wilma". The next two lines set individual characters of each of these copies. Here's the state of the variables:

Now, we set s1 to point to the characters in st1, and we set s3 to point to the second of these characters. The variables are:

It should be clear that the output will be:

UNIX> q2
s1: WiYma
s2: Wilma
s3: iYma
st1: WiYma
st2: WXlma
If you want to test it yourself, the code is in q2.cpp.


One point per line.

Question 3

Straightforward. Here is the progression -- I will include both tree and array forms:

1. Start

2. Insert 10 at the end of the array.

3. Since (10 < 60), percolate up.

4. Since (10 < 11), percolate up.
Now, we're done, and the answer
is in the array.


Four points.

Question 4


1. Start

2. Remove the last value and move it to the root.

3. Percolate Down: Since 18 is the min child, swap 18 and 99.

4. Percolate Down: Since 45 is the min child, swap 45 and 99. Since 99 has no children, We're done.


Four points.

Question 5 - 7 points

Recall the state diagram of our simulation:

When our machines enter the Up state (either in the beginning of the simulation, after repair, or after maintenance), we generate the next Failure event for the future. When we process a Maint_Begin, the next Failure event should be deleted, because maintenance affects where the next failure will occur. In order to delete the next Failure event, we need a pointer to it, and this is what is stored in failure_ptr. This as an iterator into the Event-Queue map, and we can use it to delete.

We set failure_ptr whenever we generate a failure event. In the simulation, this is in three places:

  1. The initialization code.
  2. When we repair a failure.
  3. When we complete maintenance.

As stated above, we use failure_ptr to delete the next failure event when we begin maintenance.


A correct explanation of why we need the iterator was worth three points. There are four times that failure_ptr is either used or set. Each was also worth a point.

Question 6 - 8 points

A CDF describes a probability distribution. In particular, if CDF(x) = y, then the probability that a random number generated according to that distribution is less than or equal to x is y.

A CDF plot has x on the X-axis and CDF(x) on the Y-axis.

Barney's CDF is invalid because it increases and then decreases as x grows. That makes no sense. For example, CDF(0.15) is around 0.6, and CDF(0.5) is around 0.5. That's impossible -- if the probability of generating a number less than or equal to .15 is 0.6, then the probability of generating a number less than or equal to 0.5 must be at least 0.6.

Betty's CDF is invalid because it contains values greater than 1 on the y axis. Probabilities cannot be greater than one, and since the CDF represents a probability, that graph cannot be a valit CDF graph.


Question 7

These come straight from the definition of a CDF.


2 points for part 1.

In the code, you get 2 points for implementing each part of the CDF correctly. If you made overarching mistakes, they were deducted at the end.

Question 8

This is a straightforward map program. You keep a map whose keys are the techniques (strings), and whose vals are a Data struct. In the Data struct, you'll maintain the total and number of tests so that you can compute an average. After you read standard input and have created the map, you traverse it, calculating averages and maintaining the best. When you're done with the traversal, you print the best. Here it is (in Q8.cpp):

#include <iostream>
#include <string>
#include <map>
using namespace std;

typedef struct {
  double total;
  double n;
} Data;

main(int argc, char **argv)
  map <string, Data *> all;
  map <string, Data *>::iterator mit;
  string tech;
  double t;
  double avg, bestavg;
  Data *d;

  // Read in the data, and create the map

  while (!cin.fail()) {
    cin >> tech >> t;
    if (!cin.fail()) {
      mit = all.find(tech);
      if (mit == all.end()) {
        d = new Data;
        d->total = 0;
        d->n = 0;
        all.insert(make_pair(tech, d));
      } else {
        d = mit->second;
      d->total += t;

  // Traverse the map, computing the averages, and storing the best
  // average in bestavg and the best technique in tech.

  for (mit = all.begin(); mit != all.end(); mit++) {
    d = mit->second;
    avg = d->total / d->n;
    if (mit == all.begin() || avg < bestavg) {
      bestavg = avg;
      tech = mit->first;

  // Print out the best technique

  cout << tech << endl;