15-212-X : Homework Assignment 3

**Due Wed Oct 9, 10:00 am (electronically); papers at recitation.
**

Maximum Points: 100 (+20 extra credit)

- While we acknowledge that beauty is in the eye of the beholder, you should nonetheless strive for elegance in your code. Not every program which runs deserves full credit. Make sure to state invariants in comments which are sometimes implicit in the informal presentation of an exercise. If auxiliary functions are required, describe concisely what they implement. Do not reinvent wheels and try to make your functions small and easy to understand. Use tasteful layout and avoid longwinded and contorted code. None of the problems requires more than a few lines of SML code.
- Make sure that your file compiles and runs. A program which doesn't run will not get full credit and is likely to incur a heavy penalty.
- Homeworks must be all your own work.
- Late homeworks will be accepted
**only**until start lecture on Thursday, with a 25% penalty. - If you have any questions about the assignment, contact Carsten
Schuermann at
`carsten@cs.cmu.edu`or use`cmu.andrew.academic.15-212-X.discuss`.

signature DICT = sig type key = int * int type 'a entry = key * 'a type 'a dict val empty : 'a dict val lookup : 'a dict -> key -> 'a option val insert : 'a dict * 'a entry -> 'a dict val delete : 'a dict * key -> 'a dict val map : 'a dict -> ('a -> 'b) -> 'b dict val fold : 'a dict -> ('a * 'b * 'b -> 'b) -> 'b -> b' val exists : 'a dict -> ('a entry -> bool) -> bool end; (* signature DICT *)There is partial implemenation of this structure as a

` BinarySearchTree`

. Plese extend this structure according to
the following questions.
`map d f`

should go through the whole dictionary
`d`

and apply the function `f`

to every entry,
creating a new dictonary. Write the function `map`

.
`fold d f init`

should go through the
binary tree `d`

, return
`init`

if it encounters a leaf, for every other node in the tree
it should return `f(datum,v_left,v_right)`

where
`datum`

is the datum of the node, and `v_left`

is the result
of summarizing the left subtree, `v_right`

is the result of summarizing
the right subtree. Write the function `fold`

.
`exists`

. `exists d f`

must return
`true`

if there is an entry in the database satisfying `f`

,
`false`

otherwise.
`delete`

function, here is the
what DataSoft and CMU agreed on:
- If the node to be removed has no children, just remove the node.
- If the node to be removed has one child, remove it and connect the child to the parent.
- If the node to be removed has two children, look for the
successor remove the successor, and update the entry in the node
to be removed by the successor node entry. Here, the
*successor*to a node*n*is the node whose key is greater than the key of*n*, but smaller than any other node greater than*n*. - If the node to be removed cannot be found in the tree (even if it
is empty), the result of the
`delete`

`operation should be the tree itself.`

```
Implement the
````delete`

function. Why is it always
possible to delete the successor node in the third case?
## Problem 2: The PEG game (35 points)

Another company is interested in purchasing CMU's dictionary package:
GAMESoft intends to implement the PEG solitaire game. The PEG
solitaire game is best described as follows: A PEG board contains 15
holes, shaped in form of a triangle. Every hole can be addressed by a
pair of coordinates.
Initially 14 of the holes are filled with pegs . That means there is one
empty hole somewhere on the board. In our example it is clearly `(1,2)`

.
During the game it is possible to take a peg, jump over a peg into an
empty hole. It is important that
- the jumping peg jumps 2 fields,
- the destination is an empty hole,
- and there is a peg inbetween.

It should be clear that pegs might jump into six different directions.
While jumping over a peg the jumped peg is removed. The goal of the
peg solitaire game is to jump pegs in such a way that
only one peg remains on the board eventually.
Initially GAMESoft was only interested in purchasing CMU's dictionary
package. But because of its nice implementation, GAMESoft decided to ask
you for programming help. Here is what the company has already done using
the signature `DICT`

from above:

structure Dict :> DICT = BinarySearchTree;
datatype square = Peg | Hole;
type board = square Dict.dict;
structure Dir =
struct
datatype direction =
East | NorthEast | NorthWest | West | SouthWest | SouthEast
fun increment (East) = (1,0)
| increment (NorthEast) = (0,1)
| increment (NorthWest) = (~1,1)
| increment (West) = (~1,0)
| increment (SouthWest) = (0,~1)
| increment (SouthEast) = (1,~1)
fun exists p = p East orelse p NorthEast orelse p NorthWest
orelse p West orelse p SouthWest orelse p SouthEast
end;
fun initialize (i,j) b = next (i,j) (Dict.insert (b,((i,j),Peg)))
and next (0,0) b = b
| next (i,0) b = initialize (i-1,5-i) b
| next (i,j) b = initialize (i,j-1) b;
val initialBoard = initialize (4,0) (Dict.empty);

The source code is also available.
### Question 2.1 (35 points)

Write a function `play: int -> board -> bool`

, where
`play n b`

returns `true`

if there is a
possibility to make `n`

consecutive moves otherwise false.
That means if `play 13`

applied to the initial
board returns true then there is a way
to remove all but one peg.

GAMESoft is very grateful for your support.
## Problem 3: Regular expressions (30 points +20 extra credit)

In class five different operatores have been introduced to describe
regular expressions `R`

:
- Characters
`c`

- Concatentation
`R1.R2`

- Epsilon, the empty string
`e`

- Alternative
`R1+R2`

- Empty set
`Empty`

- Repetition
`R`^{*}

This has been implemented as datatype -- as presented in class.
datatype regExp
= Char of char
| Times of regExp * regExp
| Epsilon
| Plus of regExp * regExp
| Empty
| Star of regExp

From time to time it is helpful to have some more constructs available
to form regular expressions, such as
- Don't care symbol
`_`

which accepts any
character
[[_]] = {c | c is a character}

The constructor must be called ` Underscore `

.
- Intersection
`R`_{1} & R_{2}

which
accepts a string only if it is contained in `R`_{1}

and simultanieously in `R`_{2}

.
[[R_{1} & R_{2}]] = [[R_{1}]] Intersection [[R_{2}]]

The constructor must be called ` And`

.
- Wildcard for strings
`T`

which accepts arbitrary many
characters (even 0)
[[T]] = {s | s is a string in the language}

The constructor must be called ` Top`

.
- Negation
`~ R`

which contains every string which is
not contained in `R`

.
[[~R]] = {s | s is not in [[R]]}

The constructor must be called ` Not`

.

The acceptor accept is available and
should be extended to deal with these new constructors
### Question 3.1 (10 points)

Implement the cases for don't care symbols and intersection.
### Question 3.2 (10 points)

Implement the case for Top.
### Question 3.3 (10 points)

Explain in *detail* why your implementation of the
acceptor function terminates (consider also the given cases in your
explanation).
### Question 3.4 (Extra credit 20 points)

Implement the case for Negation.
For some test data click here .

## Handin instructions

- Put your SML code into a file named ass3.sml in your ass3 directory. All
of your definitions should be in this one file. Your handin directory is

` /afs/andrew/scs/cs/15-212-X/studentdir/<your andrew id>/ass<number> `