Programming Assignment 4, Advanced Programming I

Advanced Programming I, Spring 2007

Programming Assignment 4 - An Example Solution


Table of Contents

Explanation

This page presents an example solution to the fourth programming assignment. The assignment requires a program that reads in a labeled tree and a sequence of path patterns, printing out the matches found after each pattern read. Unlike previous assignments, in which input and output were simple and obvious, input for this assignment isn't quite so clear (reading path patterns and writing path matches remain simple and obvious). In particular, how should the node information read determine how a tree gets built?

The first node read, if any, is the root of the entire tree; suppose it was read with i indentation spaces. The next node read, if it exists, has to have an indentation of j > i; otherwise the second node would be a sibling or parent of the root, which is impossible. This makes the second node a child of the root.

The third node read, if it exists, has indentation k. If k > j, then the third node is the root of a child for the second node. If k = j, then it's a sibling to the second node, which makes it a child of the second node's parent (the root, in this case). If k < j, then the third node is the root of a child for some ancestor of the second node (which, in this case, be the root again as the only ancestor of the second node; in general they may be more than one ancestor). The only case the second node can deal with is the first one, when the third node is the root of a child (k > j). The other two cases have to be handed up to an ancestor of the second node for handling.

Those observations, and the recursive nature of the trees, leads to the input_tree() procedure: read a node n to serve as the root of a subtree. Keep reading nodes and adding the subtrees as n's children as long as the new nodes have an indentation larger than n's. Otherwise stop reading nodes and return, leaving an ancestor to handle the next node.

Note the use of peek_node_tree() to look at the next node on input without reading it from intput (at least conceptually).

The public tree-input procedure should check for nodes before building the tree and check for no more nodes after building the tree.

The only other major subproblem left unsolved is searching the tree for pattern matches. Again, understanding the problem leads most of the way to a solution. Given a path pattern p1, p2, …, pn, find all subpaths n1, n2, …, nn on any path from the root to any leaf such that pi = ni for 0 < in. The find_matches() prototype is a little shaggy and should hidden behind a more presentable public interface function.

Main

Tree Input

The main tree-input procedures were explained above. The only other interesting thing about tree input is the need to support peeking at the next available node information without (conceptually) reading it. Peeking without reading can be simulated with a one-slot buffer that holds the most recently read node information. Peeking then consists of reading node information into the buffer if necessary and returning the buffer's contents. Reading and returning node information requires being aware of the buffer.

Matching Tree Paths

N-ary Trees

Path Patterns and Matches

A path pattern is nothing more than a string list in which each string is a label pattern. Path matches are stored as strings in a set, which is just a string list that doesn't add strings that are already in the list.

Sequences and String Lists

The sequence class is a reimplementation of string-list as a template class so it can be used to create sequences of any type of data values (as long as the type supports assignment). A string list is now a sequence of strings.

Index


This page last modified on 1 March 2006.