CSc 220 Assignment 6

Put It Together

Assigned
Due

Nov 15
50 pts
Dec 9

For this assignment, you are to create two template classes, rpt_queue and its inverse expand_queue. The rpt_queue class behaves somewhat like an ordinary queue, except that it groups matching items together. It allows you to push single items like a normal queue, but when you pop you get an item and a repeat count. When you push the same item three times in a row, pop gives you the item once with a repeat count of three. The expand_queue is the inverse. Its push takes an item and a count, and its pop will deliver the item the indicated number of times

The Repeating Queue

The rpt_queue template class takes a single typename template parameter giving the type of object contained in the queue. An object q of type rpt_queue<T> has the following interface:
q.push(const T &item)
Push a copy of item onto the queue.
q.pop(T &item)

Pop an item from the stack. If no item is available, the method returns zero and does nothing else. If some item is available, pop stores a copy in the parameter item, and returns a positive count of consecutive items of this value. Note that there is no such thing as an empty group: if there is something in the list, the method returns a group with at least one item; if the queue is empty there is no group to produce and the method returns 0.

Also note that contiguous matching items form a group, not isolated matches. That is, if you push 10 three times, then push 27 twice, then push 10 four more times, the pop should produce a group of three 10s, then a group of two 27s, then a group of four 10s.

q.empty() const
Returns true if q is empty, false otherwise.
For instance,
rpt_queue<int> q; q.push(10); q.push(10); q.push(3); q.push(18); q.push(18); q.push(18); q.push(10);
creates a queue which can be successfully popped four times. The first pop returns 2 and stores 10 into the parameter item; the second pop returns 1 and stores 3 into the parameter item. The third gives 3 and 18, and the fourth 1 and 10. The fifth (and any more absent another push) gives 0 and does not store anything in its parameter.

The Expanding Queue

The expand_queue template class takes a single typename template parameter giving the type of object contained in the queue. An object q of type expand_queue<T> has the following interface:
q.push(int count, const T &item)
For positive count, this pushes count repetitions of value item. For zero or negative count, push nothing; negative is meaningless, and zero is actually asking for nothing.
q.pop(T &item)
Pop an item from the stack. If no item is available, the method returns false and does nothing else. If some item is available, pop stores a copy in the parameter item removing it from q, and returns true. Item will be returned for count successive pop calls, where count is the parameter used when item was pushed.
q.empty() const
Returns true if q is empty, false otherwise.
For instance,
expand_queue<int> q; q.push(3,10); q.push(2,18); q.push(0,5); q.push(1,1);
creates a queue that can be successfully popped 6 times, giving 10, 10, 10, 18, 18, and 1. The seventh and successive pops return false and store nothing in parameter item.

Arrangement

Both of the classes are templates, so they should be placed entirely in a .h file; don't create a .cpp file. Put both in the same .h file, which you may name as you like. The examples given here assume the name rtpq.h, but this is not a requirement.

Do use the #ifndef/#define/#endif pattern as described earlier in your .h file to avoid multiple declaration errors at compile time.

Notes

You should hold your data in some private list or vector. There are basically two approaches:
  1. Your list or vector can simply hold all the items, much like an ordinary queue. If an item is repeated, it's just in list that many times.
  2. Your list or vector can hold pairs containing an item and its count, so each item in the list represents a single contiguous group.
For option 1, you will simply have a private list or vector of T to hold your data. For 2, you can either create a small (template) class holding an integer and a T, or by using std::pair. (This is the same thing std::map contains, with fields first and second.) Your private list or vector will then be of these pairs.

Option 1 may be simpler to understand, but it takes more space and each class will require a loop. In rpt_queue, push just adds each item, but pop must loop to count each group. For expand_queue, the pop just removes an item, but push will need a loop to add multiple items. Option 2 allows the classes to be written without loops. The rpt_queue push checks the tail group and either increments its count, or adds a new item with a count of 1. expand_queue push just adds one run the end of the list, and pop will just return the head item, then decrement its count and remove the item if it reaches zero.

Or you can mix and match, using different methods on each class.

You will not need to use new, or pointers of any kind in this assignment.

There is a test driver attached. Do not add your code to this file! Put your code in a .h file as instructed, then compile the test driver where it will be included. Simply placing the driver and .h files in the same directory should let you compile the driver on pretty much any system.

Submission

When your program works, is well-commented, and nicely indented, submit over the web here.