15-212-X : Homework Assignment 3

Due Wed Oct 8, 2:00pm (electronically); papers at recitation.

Maximum Points: 100 (+20 extra credit)


Guidelines


Please include needed auxiliary declarations from the ML files in /afs/andrew/cmu.edu/scs/cs/15-212-X/assignments/ass3/ in your solution file, so it compiles as is. Points will be deducted if your file does not compile by itself.

Problem 1: Dictionaries (35 points)

The company DataSoft decided recently to purchase CMU's dictionary package promising fast and easy access to their client records. The contract requires CMU to extend the signature of their dictionary package by a delete function, and a few other functions.
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 a partial implemenation of a structure BinarySearchTree with this signature in the file dict.sml. Plese extend this structure according to the following specifications.

Question 1.1 (5 points)

A call map d f should go through the whole dictionary d and apply the function f to every entry, creating a new dictionary. Write the function map.

Question 1.2 (10 points)

The function fold d f init should go through the binary tree d and return init if it encounters a leaf. For every other node in the tree it should return f(datum,vLeft,vRight) where datum is the datum of the node, and vLeft is the result of applying fold on the left subtree, vRight is the result of applying fold on the right subtree. Write the function fold.

Question 1.3 (5 points)

A call exists d p should return true if there is an entry in the database satisfying the predicate p, false otherwise. Write the function exists.

Question 1.4 (15 points)

A call delete (d, k) should return a dictionary d' in which a possible entry with key k has been removed. If there is no such entry, d' should be d. Make sure the invariant on binary search trees is preserved under this operation.

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 (1,2), which is the standard initial board.

During the game it is possible to take a peg, jump over a peg into an empty hole. The peg that was jumped over is then removed from the board. It is important that

It should be clear that pegs might jump into six different directions.

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 fullBoard = initialize (4,0) (Dict.empty);
See the file solitaire.sml for this code.

Question 2.1 (25 points)

Write a function solve : int -> board -> bool, where solve n b returns true if there is a possibility to make n consecutive moves otherwise false. That means if solve 13 applied to the initial board returns true then there is a way to remove all but one peg. Is your implementation efficient enough to determine that there cannot be 14 consecutive moves?

Question 2.2 (10 points)

Define a type solution containing enough information so that a sequence of moves can easily be replayed from it. Generalize the function from Question 2.1 to a function
findSolution : int -> board -> solution option
which returns the first found solution or NONE for the given number of moves n. Check the solution returned by findSolution 13 on the standard initial board.

Problem 3: Regular expressions (30 points + 20 extra credit)

In class five different operators have been introduced to describe regular expressions R: This has been implemented as the following datatype.
datatype regexp =
    Char of char
  | Times of regexp * regexp
  | One
  | Plus of regexp * regexp
  | Zero
  | Star of regexp;
From time to time it is helpful to have some more constructs available to form regular expressions, such as The regular expression matcher accept is available in the file regexp.sml and should be extended to deal with these new constructors. Remind yourself of the specification of the acc function and make sure your new cases fit this specification. You should also generate some test data to validate your implementation. Note that for the purposes of our implementation, the alphabet is simply any ML value of type char.

Question 3.1 (5 points)

Implement the case for the one-character wildcard _.

Question 3.2 (15 points)

Implement the case for intersection r1 & r2.

Question 3.3 (10 points)

Implement the case for T.

Question 3.4 (Extra credit, 10 points)

Prove the correctness of the case for intersection in your implementation, following the pattern in the handout.

Question 3.5 (Extra credit, 10 points)

Implement the case for Negation.

Handin instructions