HASKELL Programming Task
HASKELL Programming Task
TASK1:
The board game Black Box consists of an N x N non-empty square grid in which
are hidden a given number of “atoms”. The player tries to determine the
location of the atoms by firing a “ray” in to the grid from one of its edges. The
ray will potentially deflect or reflect by the atoms and may exit the grid at one
of the edges. The aim of the game is to deduce the location of the atoms using
the least number of rays. For Challenges 1 and 2 we will consider a variation of
this game in which the board consists of a triangular grid of equilateral triangles
arranged so:
Similar to the square grid version we hide atoms in this grid and fire rays in to
the grid to deduce their location by looking at the exit points for each ray.
Atoms are filled equilateral triangles and rays will travel in straight lines directly
through the grid unless disturbed by the presence of an atom. A ray that strikes
an atom is reflected so that its angle of incidence (always 30˚) equals its angle
of reflection (always 30˚) so that total internal reflection is 60˚.
In order to specify the location of both the atoms and the positions at which we
fire rays into and detect rays exiting from the grid we need to establish a co-
ordinate system. For atoms we simply use, counting from top-down and left to
right, the row number of the atom, along with the offset in to that row. Counting
begins at 1. For rays, we identify the "East", "West" and "South" edges of the
whole figure and count edges of each small triangle along those edges. Again,
counting is top-down and left to right and counting begins at 1. Because rays
can be fired in at one of two directions at each edge, we also use "Left" and
"Right" to identify this direction. This indicates whether the ray enters from and
exits to the left or right of the edge midpoint when facing the edge. The
diagram below indicates the naming scheme for ray edges and directions.
-
Given our naming scheme we can present examples of atoms in a grid and the
example paths that rays make take. Bear in mind that a ray may be reflected
more than once before it exists the grid.
First we have an example of a ray not being disturbed by an atom:
In some circumstances the ray may not even enter the grid and be immediately
reflected :
Finally, we see a ray that is reflected multiple times before exiting the grid :
In this exercise we will write a Haskell function that, given the size of the grid
and the location of atoms within a grid, then the function will calculate all
possible ray firings. That is, for every ray edge and direction, we calculate the
exit location for that ray.
The data types that we will use are as follows :
data EdgeDir = L | R deriving (Eq,Show,Ord)
data Face = East | West | South deriving (Eq,Show,Ord)
data EdgePoint = EP Face Int EdgeDir deriving (Eq,Show,Ord)
type Atom = (Int,Int)
Write the function
calcInteractions :: Int - > [ Atom ] - > [ ( EdgePoint , EdgePoint ) ]
that given the size of the grid and location of a number of atoms, returns the
list of pairs of entry and exit points for every possible ray. The order in which
you return these is not important. You may assume that all atom locations are
valid locations in the grid.
For example:
Test Result
TASK 2:
In this challenge we continue with the black box game as defined in Challenge
One. We use the same data types and representation of the grid.
For this challenge however we will be given a complete list of interactions with
the grid and be told the number of atoms hidden in the grid. Your task is to
write a function that finds the hidden atoms. Write a function solveTBB :: Int -
> [ (EdgePoint,EdgePoint) ] -> [Atom] that does this.
You may assume that the given list of interactions contains an entry for every
edge point of the grid. You may also return any valid solution (not all list of
interactions identify unique atom placements). By valid, we mean that if we
apply (a correct implementation of) the calcInteractions function from
Challenge One to the returned solution then this will return the given list of
interactions.
Your solution should be able to solve grids containing 4 to 5 atoms up to size 10
within approx 30 seconds. The tests have a timeout of 45 seconds.
For example:
Test Result
solveTBB 4 [(EP East 1 L,EP West 1 R),(EP East 1 [(4,3),(5,1),(6,7),
R,EP East 5 L),(EP East 2 L,EP West 2 R),(EP East (8,12)]
2 R,EP East 4 L),(EP East 3 L,EP West 3 R),(EP
East 3 R,EP South 3 L),(EP East 4 L,EP East 2 R),
(EP East 4 R,EP East 6 L),(EP East 5 L,EP East 1
R),(EP East 5 R,EP South 5 L),(EP East 6 L,EP East
4 R),(EP East 6 R,EP West 2 L),(EP East 7 L,EP
West 7 R),(EP East 7 R,EP South 7 L),(EP East 8
L,EP South 7 R),(EP East 8 R,EP South 8 L),(EP
West 1 L,EP South 8 R),(EP West 1 R,EP East 1 L),
(EP West 2 L,EP East 6 R),(EP West 2 R,EP East 2
L),(EP West 3 L,EP West 4 R),(EP West 3 R,EP East
3 L),(EP West 4 L,EP South 5 R),(EP West 4 R,EP
West 3 L),(EP West 5 L,EP West 5 R),(EP West 5
R,EP West 5 L),(EP West 6 L,EP South 3 R),(EP West
6 R,EP South 2 L),(EP West 7 L,EP South 2 R),(EP
West 7 R,EP East 7 L),(EP West 8 L,EP South 1 R),
(EP West 8 R,EP South 6 L),(EP South 1 L,EP South
4 R),(EP South 1 R,EP West 8 L),(EP South 2 L,EP
West 6 R),(EP South 2 R,EP West 7 L),(EP South 3
L,EP East 3 R),(EP South 3 R,EP West 6 L),(EP
South 4 L,EP South 6 R),(EP South 4 R,EP South 1
L),(EP South 5 L,EP East 5 R),(EP South 5 R,EP
West 4 L),(EP South 6 L,EP West 8 R),(EP South 6
R,EP South 4 L),(EP South 7 L,EP East 7 R),(EP
South 7 R,EP East 8 L),(EP South 8 L,EP East 8 R),
(EP South 8 R,EP West 1 L)]
Answer:(penalty regime: 0 %)
TASK 3:
Continuation-Passing Style (CPS) is a form of writing lambda calculus terms in
which the control of evaluation is encoded within a term as a continuation and
these are passed explicitly within functions. Think of a continuation as a function
that represents the next bit of computation to perform. You can read about this
style in many online tutorials and a good starting point is the Wikipedia page
at: https://en.wikipedia.org/wiki/Continuation-passing_style
A common translation [[E]] of a lambda calculus term to another lambda
calculus term in continuation passing style is as follows:
[[ x ]] = λ κ → (κ x)
[[ λx → E ]] = λκ → (κ λx → [[ E ]])
[[ (E1 E2) ]] = λκ → ( [[ E1 ]] λf → ( [[ E2 ]] λe → (f e κ) ) )
where the variable names k. f and e are chosen fresh so as to not capture any of
the variables of E.
We can easily extend the above translation to the lambda calculus with macros
language as described in Challenge 3 using
[[ def X = E in ME ]] = def X = [[ E ]] in [[ ME ]]
and
[[ X ]] = X
Write a function cpsTransform :: LamMacroExpr -> LamMacroExpr that translates a
lambda expression with macros in to its corresponding CPS translated form
according to the above translation rules. Take care not to capture any free
variables in the given expression during translation. Your solution may use
different variable names from those given in the example outputs. Any alpha-
equivalent answer will be acceptable.
For example:
Test Result
TASK 4:
For this challenge you will define functions to perform reduction of a lambda
expressions with macros for both innermost and outermost reduction strategies.
We will only use leftmost strategies throughout this challenge. A good starting
point is to remind yourself of the definitions of innermost and outermost
evaluation in Lecture 25 - Evaluation Strategies.
We say that a lambda expression with macros has terminated if it is an
expression without any redexes. The famous Church-Rosser theorem (for
lambda calculus) states that for different evaluation strategies any two such
terminated values will be the same, or at least alpha equivalent, lambda
expressions so they may differ only in how long a reduction sequence takes to
reach a terminated value. Note however that lambda reduction may in fact not
terminate. We are going to compare the differences between the lengths of
reduction sequences to terminated values for innermost and outermost
reduction for a given lambda expression with macros. We are also going to
compare the same lengths for the same expression when it is converted to
continuation-passing style. You may assume that there are no undefined macro
usages within the given lambda expressions but you should not assume that the
lambda expressions are closed.
Define functions:
innerRedn1 :: LamMacroExpr -> Maybe LamMacroExpr
1. Innermost reduction on E
2. Outermost reduction on E
3. Innermost reduction on the CPS translation of E applied to the identity:
[[ E ]] (λx0 → x0)
4. Outermost reduction on the CPS translation of E applied to the identity:
[[ E ]] (λx0 → x0)
Test Result
Answer:(penalty regime: 0 %)
This is the Starting code
-- Your imports here
Your report should include a second page with a bibliography listing the
source(s) for any fragments of code written by other people that you have
adapted or included directly in your submission.
There are up to 10 marks out of 40 available for this part of the assessment.
The marks will be awarded as follows:
Upto 5 marks for coding style and readability
Up to 5 marks for the approach to development and testing as described in the
report and Tests.hs file.
The tables below give guidelines for marking.
Grade Coding Style Development and Testing Strategy