Add test 1
Squashed commit of the following: commit 82aa61982e9c65f65f221fbbcdb41fe8a21321ec Author: AKP <abi@tdpain.net> Date: Thu Nov 9 12:33:56 2023 +0000 Question 5 commit 7239dcaa65545c9a5b8b634213c813438c8e52f8 Author: AKP <abi@tdpain.net> Date: Thu Nov 9 11:47:10 2023 +0000 Question 4 commit 507520373221469ea2f71ee44b67f51dbf9a2455 Author: AKP <abi@tdpain.net> Date: Thu Nov 9 11:40:56 2023 +0000 Question 3 commit 7138150a9c7f34ceb4fdb9c10a018b9cd45cb196 Author: AKP <abi@tdpain.net> Date: Thu Nov 9 11:11:26 2023 +0000 Question 2 commit 808293dff53bd033ea9138ef01a4cb2dfab8fbca Author: AKP <abi@tdpain.net> Date: Thu Nov 9 11:05:24 2023 +0000 Question 1 commit 9f4b80f7e887c0b3665e95ef1be1678e116ec2bc Author: AKP <abi@tdpain.net> Date: Thu Nov 9 11:00:25 2023 +0000 Add base files
This commit is contained in:
parent
a938af47bb
commit
0262b34e47
4 changed files with 443 additions and 0 deletions
225
test1/README.md
Normal file
225
test1/README.md
Normal file
|
@ -0,0 +1,225 @@
|
||||||
|
# Test 1
|
||||||
|
|
||||||
|
## Marking table
|
||||||
|
|
||||||
|
The exercises are defined so that it is hard to get a first-class mark.
|
||||||
|
|
||||||
|
| Mark | Cut-off |
|
||||||
|
| ------------ | ------------------ |
|
||||||
|
| 1st | 28 marks and above |
|
||||||
|
| upper second | 24-27 marks |
|
||||||
|
| lower second | 20-23 marks |
|
||||||
|
| third | 16-19 marks |
|
||||||
|
| fail | 0-15 marks |
|
||||||
|
|
||||||
|
All questions have equal weight, with eight marks each, with a total of 40
|
||||||
|
marks.
|
||||||
|
|
||||||
|
## Preparation
|
||||||
|
|
||||||
|
* The test must be completed on JupyterLab.
|
||||||
|
* Run `git pull` on JupyterLab to make sure you have the latest version of the
|
||||||
|
course repository.
|
||||||
|
* We have defined some helper functions for your in the `Types.hs` file. You are
|
||||||
|
encouraged to make use of them in your solutions.
|
||||||
|
* Do __not__ modify either the file `Types.hs` or the file
|
||||||
|
`Test1-Template.hs`.
|
||||||
|
* Copy the file `Test1-Template.hs` to a new file called
|
||||||
|
`Test1.hs` and write your solutions in `Test1.hs`.
|
||||||
|
|
||||||
|
__Don't change the header of this file, including the module declaration, and,
|
||||||
|
moreover, don't change the type signature of any of the given functions for
|
||||||
|
you to complete.__
|
||||||
|
|
||||||
|
__If you do make changes, then we will not be able to mark your submission and
|
||||||
|
hence it will receive zero marks!__
|
||||||
|
* Solve the exercises below in the file `Test1.hs`.
|
||||||
|
|
||||||
|
## Submission procedure
|
||||||
|
|
||||||
|
* If your submission doesn't compile or fails to pass the presubmit script on
|
||||||
|
JupyterLab, it will get zero marks.
|
||||||
|
* Run the presubmit script provided to you on your submission from Jupyter by
|
||||||
|
running `./presubmit.sh Test1` in the terminal (in the same folder as
|
||||||
|
your submission).
|
||||||
|
* This will check that your submission is in the correct format.
|
||||||
|
* If it is, submit it on Canvas.
|
||||||
|
* Otherwise fix and repeat the presubmission procedure.
|
||||||
|
|
||||||
|
## Plagiarism
|
||||||
|
|
||||||
|
Plagiarism will not be tolerated. Copying and contract cheating have led to full
|
||||||
|
loss of marks, and even module or degree failure, in the past.
|
||||||
|
|
||||||
|
You will need to sign a declaration on Canvas, before submission, that you
|
||||||
|
understand the [rules](/README.md#plagiarism) and are abiding by them, in order
|
||||||
|
for your submission to qualify.
|
||||||
|
|
||||||
|
## Background material
|
||||||
|
|
||||||
|
- Each question has some **Background Material**, an **Implementation Task** and
|
||||||
|
possibly some **Examples**.
|
||||||
|
- Read this material first, then implement the requested function.
|
||||||
|
- The corresponding type appears in the file `Test1-Template.hs` (to be
|
||||||
|
copied by you).
|
||||||
|
- Replace the default function implementation of `undefined` with your own
|
||||||
|
function.
|
||||||
|
|
||||||
|
## More Rules
|
||||||
|
|
||||||
|
* This is an open book test.
|
||||||
|
* You may consult your own notes, the course materials, any of the recommended
|
||||||
|
books or [Hoogle](https://hoogle.haskell.org/).
|
||||||
|
* Feel free to write helper functions whenever convenient.
|
||||||
|
* All the exercises may be solved without importing additional modules. Do not
|
||||||
|
import any modules, as it may interfere with the marking.
|
||||||
|
|
||||||
|
## Submission Deadline
|
||||||
|
|
||||||
|
* The official submission deadline is 1pm.
|
||||||
|
* If you are provided extra time by the Welfare office then your submission
|
||||||
|
deadline is 1:30pm or 2:00pm.
|
||||||
|
* Submissions close 10 minutes after your deadline, and late submissions have 5%
|
||||||
|
penalty
|
||||||
|
|
||||||
|
## Question 1 — Even majority (**8 marks**)
|
||||||
|
|
||||||
|
**Task** Write the following function `evenMajority`, that takes a list of
|
||||||
|
integers, and tells whether more than half of them are even.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
evenMajority :: [Int] -> Bool
|
||||||
|
evenMajority ns = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
## Question 2 — 5-smooth numbers (**8 marks**)
|
||||||
|
|
||||||
|
A 5-smooth number is an integer which has no prime factor larger than 5. For an
|
||||||
|
integer N, we define S(N) as the set of 5-smooth numbers less than or equal to
|
||||||
|
N. For example S(20) = {1,2,3,4,5,6,8,9,10,12,15,16,18,20}
|
||||||
|
|
||||||
|
**Task** Define the following function `get5SmoothNumbers`, that gives a list of
|
||||||
|
all 5-smooth numbers less than or equal to a given number.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
get5SmoothNumbers :: Int -> [Int]
|
||||||
|
get5SmoothNumbers k = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
*Test1> get5SmoothNumbers 25
|
||||||
|
[1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25]
|
||||||
|
|
||||||
|
*Test1> get5SmoothNumbers 50
|
||||||
|
[1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Question 3 — Train stops (**8 marks**)
|
||||||
|
|
||||||
|
Consider the following type of train stops on the West Midlands Railway line,
|
||||||
|
from Redditch to Birmingham New Street.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
data TrainStop = BirminghamNewStreet
|
||||||
|
| FiveWays
|
||||||
|
| University
|
||||||
|
| SellyOak
|
||||||
|
| Bournville
|
||||||
|
| KingsNorton
|
||||||
|
| Northfield
|
||||||
|
| Longbridge
|
||||||
|
| BarntGreen
|
||||||
|
| Alvechurch
|
||||||
|
| Redditch
|
||||||
|
deriving (Eq, Show)
|
||||||
|
```
|
||||||
|
|
||||||
|
We define the function `theStopAfter` on this type, which encodes the
|
||||||
|
information of which stop comes immediately after which stop.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
theStopAfter :: TrainStop -> TrainStop
|
||||||
|
theStopAfter Redditch = Alvechurch
|
||||||
|
theStopAfter Alvechurch = BarntGreen
|
||||||
|
theStopAfter BarntGreen = Longbridge
|
||||||
|
theStopAfter Longbridge = Northfield
|
||||||
|
theStopAfter Northfield = KingsNorton
|
||||||
|
theStopAfter KingsNorton = Bournville
|
||||||
|
theStopAfter Bournville = SellyOak
|
||||||
|
theStopAfter SellyOak = University
|
||||||
|
theStopAfter University = FiveWays
|
||||||
|
theStopAfter FiveWays = BirminghamNewStreet
|
||||||
|
theStopAfter BirminghamNewStreet = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the function is undefined on `BirminghamNewStreet` because that is the
|
||||||
|
last possible stop on this line. You should ensure that this function is never
|
||||||
|
called on `BirminghamNewStreet`, because the program will crash if you do that.
|
||||||
|
|
||||||
|
**Task** Define the following function `comesBefore`, using the given
|
||||||
|
`theStopAfter` function, such that `comesBefore s1 s2` is `True` if and only if
|
||||||
|
`s1` is a stop preceding stop `s2`.
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
comesBefore :: TrainStop -> TrainStop -> Bool
|
||||||
|
comesBefore s1 s2 = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
Some examples:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
*Test1> comesBefore University BirminghamNewStreet
|
||||||
|
True
|
||||||
|
*Test1> comesBefore Bournville FiveWays
|
||||||
|
True
|
||||||
|
*Test1> comesBefore BirminghamNewStreet University
|
||||||
|
False
|
||||||
|
*Test1> comesBefore University KingsNorton
|
||||||
|
False
|
||||||
|
*Test1> comesBefore University University
|
||||||
|
False
|
||||||
|
```
|
||||||
|
|
||||||
|
## Question 4 — Repeated applications of a function (**8 marks**)
|
||||||
|
|
||||||
|
**Task** Write a function `countApplications`
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
countApplications :: (a -> a) -> (a -> Bool) -> a -> Int
|
||||||
|
countApplications f p x = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
that takes
|
||||||
|
|
||||||
|
1. a function `f :: a -> a`,
|
||||||
|
1. a termination condition `p :: a -> Bool`, and
|
||||||
|
1. an input `x :: a`,
|
||||||
|
|
||||||
|
and counts the number of times that the function `f` must be repeatedly applied
|
||||||
|
to `x` until the output satisfies the condition `p`.
|
||||||
|
|
||||||
|
Here is an example of how to use this function:
|
||||||
|
|
||||||
|
```hs
|
||||||
|
*Test1> countApplications (\n -> n `div` 2) odd 8
|
||||||
|
3
|
||||||
|
*Test1> countApplications (\n -> n `div` 2) odd 10
|
||||||
|
1
|
||||||
|
```
|
||||||
|
|
||||||
|
We will only test your implementation of `countApplications` on functions that
|
||||||
|
do terminate with respect to the termination condition.
|
||||||
|
|
||||||
|
## Question 5 — Higher order functions (**8 marks**)
|
||||||
|
|
||||||
|
**Task** Write a function `f` of the following type
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
f :: (a -> a -> r) -> ((a -> r) -> a) -> r
|
||||||
|
f g h = undefined
|
||||||
|
```
|
||||||
|
|
||||||
|
The function should terminate for all terminating inputs. Your solution should
|
||||||
|
not use recursion or `undefined`.
|
59
test1/Test1.hs
Normal file
59
test1/Test1.hs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
-- setting the "warn-incomplete-patterns" flag asks GHC to warn you
|
||||||
|
-- about possible missing cases in pattern-matching definitions
|
||||||
|
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
|
||||||
|
|
||||||
|
-- see https://wiki.haskell.org/Safe_Haskell
|
||||||
|
{-# LANGUAGE Safe #-}
|
||||||
|
|
||||||
|
module Test1 ( evenMajority
|
||||||
|
, get5SmoothNumbers
|
||||||
|
, comesBefore
|
||||||
|
, countApplications
|
||||||
|
, f
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Types
|
||||||
|
|
||||||
|
{- QUESTION 1 -}
|
||||||
|
|
||||||
|
_countEvens :: [Int] -> Int
|
||||||
|
_countEvens ns = foldl (\acc x -> if even x then acc + 1 else acc) 0 ns
|
||||||
|
|
||||||
|
evenMajority :: [Int] -> Bool
|
||||||
|
evenMajority ns = let half = (length ns) `div` 2 in (_countEvens ns) > half
|
||||||
|
|
||||||
|
{- QUESTION 2 -}
|
||||||
|
|
||||||
|
_is5Smooth :: Int -> Bool
|
||||||
|
_is5Smooth n = foldl (\acc x -> acc && x <= 5) True (primeFactors n)
|
||||||
|
|
||||||
|
get5SmoothNumbers :: Int -> [Int]
|
||||||
|
get5SmoothNumbers n = filter _is5Smooth [1..n]
|
||||||
|
|
||||||
|
{- QUESTION 3 -}
|
||||||
|
|
||||||
|
_getStationsBefore :: TrainStop -> Maybe TrainStop -> [TrainStop]
|
||||||
|
_getStationsBefore finalStop Nothing = _getStationsBefore finalStop (Just Redditch)
|
||||||
|
_getStationsBefore finalStop (Just previousStop) | finalStop == previousStop = []
|
||||||
|
| otherwise = previousStop:(_getStationsBefore finalStop (Just (theStopAfter previousStop)))
|
||||||
|
|
||||||
|
comesBefore :: TrainStop -> TrainStop -> Bool
|
||||||
|
comesBefore s1 s2 = not (foldl (\acc x -> acc && x /= s1) True (_getStationsBefore s2 Nothing))
|
||||||
|
|
||||||
|
{- QUESTION 4 -}
|
||||||
|
|
||||||
|
_countApplications :: (a -> a) -> (a -> Bool) -> a -> Int -> Int
|
||||||
|
_countApplications f p acc tries | (p acc) = tries
|
||||||
|
| otherwise = _countApplications f p (f acc) (tries + 1)
|
||||||
|
|
||||||
|
countApplications :: (a -> a) -> (a -> Bool) -> a -> Int
|
||||||
|
countApplications f p x = _countApplications f p x 0
|
||||||
|
|
||||||
|
{- QUESTION 5 -}
|
||||||
|
|
||||||
|
_cloneArgument :: (a -> a -> r) -> (a -> r)
|
||||||
|
_cloneArgument f = (\x -> f x x)
|
||||||
|
|
||||||
|
f :: (a -> a -> r) -> ((a -> r) -> a) -> r
|
||||||
|
f g h = let i = (_cloneArgument g) in
|
||||||
|
g (h i) (h i)
|
56
test1/Types.hs
Normal file
56
test1/Types.hs
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
-- setting the "warn-incomplete-patterns" flag asks GHC to warn you
|
||||||
|
-- about possible missing cases in pattern-matching definitions
|
||||||
|
{-# OPTIONS_GHC -fwarn-incomplete-patterns #-}
|
||||||
|
|
||||||
|
-- see https://wiki.haskell.org/Safe_Haskell
|
||||||
|
{-# LANGUAGE Safe #-}
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
-------------------------- DO **NOT** MODIFY THIS FILE --------------------------
|
||||||
|
---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
module Types where
|
||||||
|
|
||||||
|
-- Question 2
|
||||||
|
|
||||||
|
factors :: Int -> [Int]
|
||||||
|
factors n = [ k | k <- [1..n] , n `mod` k == 0 ]
|
||||||
|
|
||||||
|
isPrime :: Int -> Bool
|
||||||
|
isPrime n = factors n == [1, n]
|
||||||
|
|
||||||
|
primeFactors :: Int -> [Int]
|
||||||
|
primeFactors n = [x | x <- [1..n], n `mod` x == 0 && isPrime x]
|
||||||
|
|
||||||
|
-- Question 3
|
||||||
|
|
||||||
|
data TrainStop = BirminghamNewStreet
|
||||||
|
| FiveWays
|
||||||
|
| University
|
||||||
|
| SellyOak
|
||||||
|
| Bournville
|
||||||
|
| KingsNorton
|
||||||
|
| Northfield
|
||||||
|
| Longbridge
|
||||||
|
| BarntGreen
|
||||||
|
| Alvechurch
|
||||||
|
| Redditch
|
||||||
|
deriving (Eq, Show)
|
||||||
|
|
||||||
|
theStopAfter :: TrainStop -> TrainStop
|
||||||
|
theStopAfter Redditch = Alvechurch
|
||||||
|
theStopAfter Alvechurch = BarntGreen
|
||||||
|
theStopAfter BarntGreen = Longbridge
|
||||||
|
theStopAfter Longbridge = Northfield
|
||||||
|
theStopAfter Northfield = KingsNorton
|
||||||
|
theStopAfter KingsNorton = Bournville
|
||||||
|
theStopAfter Bournville = SellyOak
|
||||||
|
theStopAfter SellyOak = University
|
||||||
|
theStopAfter University = FiveWays
|
||||||
|
theStopAfter FiveWays = BirminghamNewStreet
|
||||||
|
theStopAfter BirminghamNewStreet = undefined
|
||||||
|
|
||||||
|
-- Question 4
|
||||||
|
|
||||||
|
divideBy2 :: Int -> Int
|
||||||
|
divideBy2 n = n `div` 2
|
103
test1/presubmit.sh
Normal file
103
test1/presubmit.sh
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
if [ "$1" = "" ]
|
||||||
|
then
|
||||||
|
echo "You forgot to add the assignment name, e.g. 'Assessed1'."
|
||||||
|
echo "Please run the script again with the right argument."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -f "$1.hs" ]
|
||||||
|
then
|
||||||
|
echo "File '$1.hs' not found."
|
||||||
|
echo "Are you in the correct directory?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Trying to compile your submission..."
|
||||||
|
|
||||||
|
# Create temporary directory
|
||||||
|
temp_dir=$(mktemp -d)
|
||||||
|
|
||||||
|
ghc $1.hs -odir $temp_dir -hidir $temp_dir
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo ""
|
||||||
|
echo "Your file '$1.hs' did not compile."
|
||||||
|
echo "Please fix it before submitting."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -f "$temp_dir/$1.o" ]
|
||||||
|
then
|
||||||
|
echo ""
|
||||||
|
echo "The module name in '$1.hs' does match not the filename '$1'."
|
||||||
|
echo "Please make sure you that"
|
||||||
|
echo -e "\t(i) your file is called something like 'TestX.hs'"
|
||||||
|
echo -e "\t(ii) you did not change the top of the template"
|
||||||
|
echo "and try again."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
ghc -XSafe $1.hs -odir $temp_dir -hidir $temp_dir
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo ""
|
||||||
|
echo "Your file did not compile with '-XSafe.'"
|
||||||
|
echo "Did you remove '{-# LANGUAGE Safe #-}' from the template?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create file for ensuring type signatures have not been modified
|
||||||
|
|
||||||
|
cat >> $temp_dir/Signatures.hs << 'END'
|
||||||
|
{-# LANGUAGE Safe #-}
|
||||||
|
module Signatures where
|
||||||
|
|
||||||
|
import Types
|
||||||
|
import Test1
|
||||||
|
|
||||||
|
{- QUESTION 1 -}
|
||||||
|
|
||||||
|
evenMajorityTest :: [Int] -> Bool
|
||||||
|
evenMajorityTest = evenMajority
|
||||||
|
|
||||||
|
{- QUESTION 2 -}
|
||||||
|
|
||||||
|
get5SmoothNumbersTest :: Int -> [Int]
|
||||||
|
get5SmoothNumbersTest = get5SmoothNumbers
|
||||||
|
|
||||||
|
{- QUESTION 3 -}
|
||||||
|
|
||||||
|
comesBeforeTest :: TrainStop -> TrainStop -> Bool
|
||||||
|
comesBeforeTest = comesBefore
|
||||||
|
|
||||||
|
{- QUESTION 4 -}
|
||||||
|
|
||||||
|
countApplicationsTest :: (a -> a) -> (a -> Bool) -> a -> Int
|
||||||
|
countApplicationsTest = countApplications
|
||||||
|
|
||||||
|
{- QUESTION 5 -}
|
||||||
|
|
||||||
|
fTest :: (a -> a -> r) -> ((a -> r) -> a) -> r
|
||||||
|
fTest = f
|
||||||
|
END
|
||||||
|
|
||||||
|
ghc -XSafe $temp_dir/Signatures.hs -odir $temp_dir -hidir $temp_dir
|
||||||
|
|
||||||
|
if [ $? -ne 0 ]
|
||||||
|
then
|
||||||
|
echo ""
|
||||||
|
echo "Your file did not compile with the correct type signatures."
|
||||||
|
echo "Did you modify the type signatures from the template?"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "All checks passed."
|
||||||
|
echo "You are ready to submit!"
|
||||||
|
|
||||||
|
# Cleanup temporary directory
|
||||||
|
rm -r $temp_dir
|
Reference in a new issue