COMP 302 Programming Languages and Paradigms Assignment 5


Category: You will Instantly receive a download link for .zip solution file upon Payment


5/5 - (3 votes)

[Question 1:70 points]
In this question you will implement a simple map colouring problem. We will represent a map
showing countries by describing which countries share a border. A country is just a string. A chart
is simply a map (in the normal sense of the word) of some countries. It is represented as a list
of pairs of countries. If (a, b) is in the list it means that the countries a and b share a border.
This relation is symmetric but we will not put both (a, b) and (b, a) in the list. We want to colour
the chart so that two countries that share a border are not given the same colour. We will not
name the colours; we simply view a colour as a set of countries that share the same colour; such
a set is represented as a list of countries. A colouring is a set of colours; hence a set of sets of
countries: this is represented as a list of lists of countries. The algorithm takes a chart, and an
initially empty colouring and then tries to extend the colouring by adding countries from the chart.
It works by naively checking if a country can be added to a given colour by making sure that it is
not a neighbour of any of the countries already with that colour.
Here are the type definitions and names of functions:
# type country = string
# type chart = (country * country) list
# type colour = country list
# type colouring = colour list
val areNeighbours : country -> country -> chart -> bool =
val canBeExtBy : colour -> country -> chart -> bool =
val extColouring : chart -> colouring -> country -> colour list =
val removeDuplicates : ’a list -> ’a list =
val countriesInChart : chart -> country list =
val colourTheCountries : chart -> colouring =
You are required to implement all these functions. This time you are encouraged to use functions
from the list library. I found List.mem, List.for_all, List.filter and List.fold_left to be
useful in my solution. Of course, you can program without these for full credit but you will find
that the solutions using these are short and sweet.
[Question 2:30 points]
This exercise shows you how to do low-level pointer manipulation in OCaml if you ever need to do
that. We can define linked lists as follows:
type cell = { data : int; next : rlist}
and rlist = cell option ref
Notice that this is a mutually recursive definition. Each type mentions the other one. The keyword
and is used for mutually recursive definitions.
Implement an OCaml function insert which inserts an element into a sorted linked list and preserves the sorting. You do not have to worry about checking if the input list is sorted. The type
should be
val insert : comp:(int * int -> bool) -> item:int -> list:rlist -> unit
Insert takes in three arguments: A comparison function of type int * int -> bool, an element
of type int and a linked list l of type rlist. Your function will destructively update the list
l. This means that you will have mutable fields that get updated. Please note the types carefully.
Here is the code I used to test the program.
let c1 = {data = 1; next = ref None}
let c2 = {data = 2; next = ref (Some c1)}
let c3 = {data = 3; next = ref (Some c2)}
let c5 = {data = 5; next = ref (Some c3)}
(* This converts an rlist to an ordinary list. *)
let rec displayList (c : rlist) =
match !c with
| None -> []
| Some { data = d; next = l } -> d :: (displayList l)
(* Useful if you are creating some cells by hand and then converting
them to rlists as I did above. *)
let cell2rlist (c:cell):rlist = ref (Some c)
(* Example comparison function. *)
let bigger(x:int, y:int) = (x > y)
You may find the displayList and cell2rlist functions useful.
Here are examples of the code in action:
# let l5 = cell2rlist c5;;
val l5 : rlist = ….
(* Messy display deleted. *)
# displayList l5;;
– : int list = [5; 3; 2; 1]
# displayList l5;;
– : int list = [5; 3; 2; 1]
# insert bigger 4 l5;;
– : unit = ()
# displayList l5;;
– : int list = [5; 4; 3; 2; 1]
# insert bigger 9 l5;;
– : unit = ()
# displayList l5;;
– : int list = [9; 5; 4; 3; 2; 1]
# insert bigger 0 l5;;
– : unit = ()
# displayList l5;;
– : int list = [9; 5; 4; 3; 2; 1; 0]
The program is short (5 lines or fewer) and easy to mess up. Please think carefully about whether
you are creating aliases or not. You can easily write programs that look absolutely correct but
which create infinite loops. It might happen that your insert program looks like it is working
correctly but then displayList crashes. You might then waste hours trying to “fix” displayList
and cursing me for writing incorrect code. Most likely, your insert happily terminated but created
a cycle of pointers which then sends displayList into an infinite loop.