Past Practical Exam Questions

Big

For the following task you should define the function view as follows:
view = (putStr.unlines)

Suppose we wish to represent the digit 0 by the list of lists:

[" *** ",
" * * ",
" * * ",
" *** "]

and the digit 1 by

[" * ",
" * ",
" * ",
" * "]

Write a function big :: String -> [String] which takes as input a list '0's and '1's, and returns a list of strings which represent the number in the above big format. For example:

Prac> big "11"
[" *  * ", " *  * ", " *  * ", " *  * "]
Prac> view (big "11")
 *  *
 *  *
 *  *
 *  *

Prac> big "10"
[" *  *** ", " *  * * ", " *  * * ", " *  *** "]
Prac> view (big "10")
 *  ***
 *  * *
 *  * *
 *  ***

Prac> big "100"
[" *  ***  *** ", " *  * *  * * ", " *  * *  * * ", " *  ***  *** "]

Prac> view (big "100")
 *  ***  ***
 *  * *  * *
 *  * *  * *
 *  ***  ***

Prac> view (big "1011")
 *  ***  *  *
 *  * *  *  *
 *  * *  *  *
 *  ***  *  *

9

rotate

Write a function rotate :: [[Char]] -> [[Char]] which takes in a rectangular grid of characters and returns the grid rotated 90 degrees clockwise.

For example, rotating the grid:

["ABCDE",
 "vwxyz",
 "....."]

produces the grid:

[".vA",
 ".wB",
 ".xC",
 ".yD",
 ".zE"]

You may assume that the grid is rectangular and non empty.

here are some examples of how your function is to behave:

Pexam> rotate ["*"]
["*"]
Pexam> rotate ["Two","Row"]
["RT", "ow", "wo"]
Pexam> rotate ["One","For","All"]
["AFO", "lon", "lre"]
Pexam> rotate ["123456789"]
["1", "2", "3", "4", "5", "6", "7", "8", "9"]
Pexam> rotate ["1", "2", "3", "4", "5", "6", "7", "8", "9"]
["987654321"]
Pexam> rotate ["Four","Rows","Four","Cols"]
["CFRF", "oooo", "luwu", "srsr"]

tp8231

Add list

An add_list for a positive integer n is a list of positive integers whose sum is n, arranged in decreasing order. For example [3,1,1] is an add_list for 5.

Recall that a positive integer means an integer greater than 0.

Write a function sums :: Int -> [[Int]] which, given a positive integer n, returns a list of its add_lists.

The add_lists may be returned in any order, it does not matter. For example sums 2 may return either [[1,1], [2]] or [[2], [1,1]]

Here are some further examples:

Main> sums 1
[[1]]
Main> sums 2
[[1, 1], [2]]
Main> sums 3
[[1, 1, 1], [2, 1], [3]]
Main> sums 4
[[1, 1, 1, 1], [2, 1, 1], [2, 2], [3, 1], [4]]
Main> sums 5
[[1, 1, 1, 1, 1], [2, 1, 1, 1], [2, 2, 1], [3, 1, 1], [3, 2], [4, 1], [5]]
Main> length (sums 10)
42
Main> length (sums 5)
7

tp8252

loop

Consider the infinte list: n, next n, next (next n), next (next (next n))),.., where next is defined as:

next :: Int -> Int
next n
  | even n    = n `div` 2
  | otherwise = n * 3 - 1

If we start with 4 we get the sequence: 4,2,1,2,1,2,1,2.... This has a loop of length 2.

Similarly if we start with 5 we get the sequence: 5,14,7,20,10,5,14,7,20,10,5,14,..., which has a loop of length 5.

Write a function loop :: Int -> Int which returns the loop length of the sequence for a specified starting number.

You may assume that the input is greater than zero. If nessesary you may also assume that the first full cycle of the loop is contained in the first 60 elements of the infinte list (we will only test starting numbers for which this is true.) Tests have shown that these conditions apply to all starting numbers between 1 and 100.

Pexam> loop 2
2
Pexam> loop 5
5
Pexam> loop 3
2
Pexam> loop 7
5
Pexam> loop 29
2
Pexam> loop 66
18
Pexam> loop 500
5

tp8232

Trap

Pascal's trapezium is an series of rows of numbers. Here are the first few rows:

     
         1 1 1
        1 2 2 1
       1 3 4 3 1
      1 4 7 7 4 1
     and so on   . . . 

Each number is the sum of the two numbers above it. End numbers are 1. We call the top row "row 0", the next row "row 1" and so on. Similarly, we call the leftmost number in a row "column 0", the next number "column 1", and so on.

We can represent the trapezium in Haskell using a list of lists of Int. So row 2 would be [1, 3, 4, 3, 1], row 4 would be [1, 5, 11, 14, 11, 5, 1]. We can represent individual elements using (row,column) coordinates, so element (0,0) woud be 1, and (3,4) is 4.

Write a function trap :: (Int,Int) -> Int which takes in a pair of coordinates and returns the corresponding element in the trapezium.

For example:

Pexam> trap (0,0)
1
Pexam> trap (3,4)
4
Pexam> trap (1,1)
2
Pexam> trap (6,1)
7
Pexam> trap (4,3)
14
Pexam> trap (11,5)
957

tp8241

lock

Note: Widdershins means anti-clockwise.

Consider the lock on a safe. It consists of a dial is numbered from 0 to 35. You operate it by rotating the dial clockwise and widdershins certain amounts. An output is generated every time the dial changes direction, and when it finally stops.

For example, suppose that the dial is initially pointing to 0. We can generate the sequence 6,4,5 by rotating 6 steps in a widdershins direction, then 2 steps in a clockwise direction, then 1 step widdershins. Or we could have rotated 30 steps clockwise, 34 steps widdershins, 35 steps clockwise.

Define a rotation type as follows:

data Rotation = Clockwise Int | Widdershins Int
   deriving (Show, Eq)

Write a function lock :: [Rotation] -> [Int] which returns the output sequence generated by a list of rotations. You may assume that the list of rotations is not empty, and that the dial is initially pointing to 0.

For example:

Pexam> lock [(Widdershins 6),(Clockwise 2),(Widdershins 1)]
[6, 4, 5]
Pexam> lock [(Widdershins 1),(Widdershins 1),(Widdershins 1)]
[3]
Pexam> lock [(Widdershins 100)]
[28]
Pexam> lock [(Clockwise 30),(Widdershins 34),(Clockwise 35)]
[6, 4, 5]
Pexam> lock [(Clockwise 4),(Widdershins 1)]
[32, 33]
Pexam> lock [(Clockwise 4),(Widdershins 1),(Widdershins 3),
(Clockwise 20),(Widdershins 6),(Clockwise 5),(Clockwise 5),
(Widdershins 8)]
[32, 0, 16, 22, 12, 20]

tp8242