Assignments | Class Photo | Computing Resources | Course Home | Lab Hours/Tutoring | Schedule | Submit

Saint Louis University

Computer Science 180
Data Structures

Michael Goldwasser

Fall 2008

Dept. of Math & Computer Science

Programming Assignment 07

Programming Contest

Due: Monday, 8 December 2008, 11:59pm

Please see the general programming webpage for details about the programming environment for this course, guidelines for programming style, and details on electronic submission of assignments.

Collaboration Policy

For this assignment, you are allowed to work with one other student if you wish (in fact, we suggest that you do so). If any student wishes to have a partner but has not been able to locate one, please let the instructor know so that we can match up partners.

Please make sure you adhere to the policies on academic integrity in this regard.


Contents:


Overview

Every year, the Association for Computing Machinery (ACM) holds the International Collegiate Programming Contest (ICPC). Last year's contest involved 6787 teams from 83 countries, including several teams from SLU. Teams compete in the Fall at the regional level, and the top teams from those regions compete at the Finals in the Spring. If anyone has interest in participating in future years, please let me know and I'll add you to the mailing list for next Fall.

The contest format is as follows. Students work in teams of three to solve as many problems as possible in a five-hour time period. Each problem has a formal description including the precise format for input and the expectations and formatting requirements for the resulting output. Sample input and output is provided, but the judges run each submitted project on a larger set of test cases. To get credit for a problem, the program must work perfectly on all test cases; otherwise, the team is informed that the program fails and they may attempt to revise and resubmit the code (albeit with a penalty assessed). However, the judges do not inform the students of the precise problem. All students are told is that they had the wrong output (or in a handful of exceptional cases, are told other information such as that the program didn't compile, or that it had not terminated yet after one minute of processing time).

For our final programming assignment this semester, I want you to (individually) solve one of the problems that appeared in a recent regional contest. After describing the problem, I am going to give you a bit of a hint that was not afforded the competitors. But first, I will present the problem description in its original form.


The Official Problem Statement

Trees have many applications in computer science. Perhaps the most commonly used trees are rooted binary trees, but there are other types of rooted trees that may be useful as well. One example is ordered trees, in which the subtrees for any given node are ordered. The number of children of each node is variable, and there is no limit on the number. Formally, an ordered tree consists of a finite set of nodes T such that Also, define root(T1), ..., root(Tm) to be the children of root(T), with root(Ti) being the i-th child. The nodes root(T1), ..., root(Tm) are siblings.

It is often more convenient to represent an ordered tree as a rooted binary tree, so that each node can be stored in the same amount of memory. The conversion is performed by the following steps:

  1. remove all edges from each node to its children;
  2. for each node, add an edge to its first child in T (if any) as the left child;
  3. for each node, add an edge to its next sibling in T (if any) as the right child.

This is illustrated by the following:

         0                             0
       / | \                          /
      1  2  3       ===>             1
        / \                           \
       4   5                           2
                                      / \
                                     4   3
                                      \
                                       5
In most cases, the height of the tree (the number of edges in the longest root-to-leaf path) increases after the conversion. This is undesirable because the complexity of many algorithms on trees depends on its height.

You are asked to write a program that computes the height of the tree before and after the conversion.

Input

The input to the program should be read from a file named graft.in. You may declare a file stream for reading this using the declaration

ifstream fin("graft.in");

The input is given by a number of lines giving the directions taken in a pre-order traversal of the trees. There is one line for each tree. For example, the tree above would give dudduduudu, meaning 0 down to 1, 1 up to 0, 0 down to 2, etc. The input is terminated by a line whose first character is #. You may assume that each tree has at least 2 and no more than 10000 nodes.

Output

The output for your program should be printed directly to the console using cout.

For each tree, print the heights of the tree before and after the conversion specified above. Use the format:

Tree t: h1 => h2
where t is the case number (starting from 1), h1 is the height of the tree before the conversion, and h2 is the height of the tree after the conversion.

Sample Input

dudduduudu
ddddduuuuu
dddduduuuu
dddduuduuu
#

Sample Output

Tree 1: 2 => 4
Tree 2: 5 => 5
Tree 3: 4 => 5
Tree 4: 4 => 4

Hints

Student competing in the contest were given no advice beyond the official problem description. They had to determine a strategy for solving the problem and then implement their approach. At first glance, this problem might require a good deal of work. The sequence of down/up commands is sufficient for reconstructing the general tree. Teams might have designed their own general tree representation, built the general tree and measured its depth, and then designed an algorithm for converting the original tree to the binary representation, again measuring the resulting depth.

If you'd like, you are welcome to build up the tree structures in your program. But, as is often the case for contest problems, there is an easier way. It is possible to compute the resulting depths without ever building the trees. If you are careful, you can think of this as an iterator walking the tree, and maintain information to compute the current depth of the node you are visiting at any point in time. If you can do that, then you can also track the maximum depth ever reached.

You need to do this for both implicit tree representations. We suggest that you start by thinking about the first task, of computing the maximum depth achieved in the original general tree. That's an easy one to compute. The more challenging task is to devise a way to track presumed depths in the binary-tree representation. Yet, there is a way!


Testing Your Program

If this were really a contest, you are allowed to submit your source code to the judges to see if it passes all of their tests. They use the sample input/output as part of the test, but many others as well.

To give you a similar experience, we have prepared an automated way to test your own code from turing. You may execute the following command from the directory containing your source code.

     /Public/goldwasser/icpc/test graft.cpp
It reports whether or not you've succeeded (but if you are wrong, it does not provide detailed feedback).

Note: You are welcome to use this tool as often as you'd like. However, you must use our regular submissions system for turning in your project to be graded. See the next section for details.


Files to Submit

Please submit the following:


Grading Standards

The assignment is worth 10 points.


Michael Goldwasser
CSCI 180, Fall 2008
Last modified: Sunday, 30 November 2008
Assignments | Class Photo | Computing Resources | Course Home | Lab Hours/Tutoring | Schedule | Submit