Skip to content

Commit 0b94664

Browse files
committed
common format
1 parent 2857bae commit 0b94664

9 files changed

Lines changed: 272 additions & 236 deletions

File tree

exams/convex-hull/index.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,8 @@ Your file has to be called `convexhull.rkt` and must provide the function
111111
; your code goes here
112112
```
113113

114+
### Hints
115+
114116
_**Hint \#2 (Polar Angle)**_
115117
In Scheme, you can compute the polar angle of a vector $\vec v=(x,y)$ with
116118
```racket
@@ -238,6 +240,7 @@ import Data.List -- for sortBy
238240
-- your code goes here
239241
```
240242

243+
### Hints
241244

242245
_**Hint \#4 (Polar Angle):**_
243246
In Haskell, you can compute the polar angle of a vector `v = (x,y)` with

exams/fermat-primality/index.md

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ This probabilistic primality test is known as the *Fermat Primality Test*. Note
2121
*Carmichael numbers*, which are composite yet pass the test for all $a$ relatively prime to the
2222
respective number, are avoided when testing your implementation of this task.
2323

24-
## Pseudo-random Number Generation
24+
### Pseudo-random Number Generation
2525

2626
To generate pseudorandom numbers in a given interval, use
2727
the *Linear Congruential Generator (LCG)*
@@ -35,11 +35,11 @@ $$
3535
b' = (b \ \texttt{mod}\, (b^\text{upper} - b^\text{lower})) + b^\text{lower}.
3636
$$
3737

38+
## Haskell
3839

39-
Your task is to implement the Fermat Primality Test in Haskell.
40-
There are two parts to this task: first, implement the LCG, and then the test itself.
40+
Your task is to implement the Fermat Primality Test in Haskell. Your file should be called `Fermat.hs`, and you should export the function `primality :: Int -> Int -> State LCG Bool`. There are two parts to this task: first, implement the LCG, and then the test itself.
4141

42-
## Implementation
42+
### Implementation
4343

4444
The LCG generator is represented as
4545
```haskell
@@ -84,45 +84,40 @@ False
8484
True
8585
```
8686

87-
## Hint
87+
### Hint
8888

8989
To prevent overflow of `Int`, compute $a^{p-1}\mod p$ sequentially using
9090
the identity $a^{k+1}\mod p = a\cdot (a^k\mod p)\mod p$, i.e.,
9191
sequentially multiplying by $a$ and applying modulo to each partial result.
9292

9393
::: details Exam Solution
9494
```haskell
95+
module Fermat (LCG (..), primality) where
96+
97+
import Control.Monad
9598
import Control.Monad.State
9699

97-
---- linear congruential generator
98-
data LCG = LCG Int Int Int Int deriving Show -- A*x + C mod M
100+
-- Linear congruential generator
101+
-- A*x + C mod M
102+
data LCG = LCG Int Int Int Int deriving (Show)
103+
104+
lcg (LCG a x c m) =
105+
let y = (a * x + c) `mod` m
106+
in (y, LCG a y c m)
99107

100-
generate :: State LCG Int
101-
generate = do (LCG a x c m) <- get
102-
let x' = (a * x + c) `mod` m
103-
put (LCG a x' c m)
104-
return x'
108+
generate = state lcg
105109

106-
generate_range :: Int -> Int -> State LCG Int -- a <= x < b
107-
generate_range a b = do x <- generate
108-
let x' = (x `mod` (b-a)) + a
109-
return x'
110+
project low high num = (num `mod` (high - low)) + low
110111

111-
modulo_power :: Int -> Int -> Int -> Int
112-
modulo_power a n m = iter a n where
113-
iter b 1 = b
114-
iter b nn = iter (b*a `mod` m) (nn-1)
112+
generateRange low high = project low high <$> generate
115113

116-
fermat_comp :: Int -> Int -> Int
117-
fermat_comp p b = (modulo_power b (p-1) p)
114+
moduloPower a n m = iterate (\x -> x * a `mod` m) 1 !! n
118115

119-
fermat_check :: Int -> Int -> Int -> State LCG Bool
120-
fermat_check p n 1 = primality p (n-1)
121-
fermat_check _ _ _ = return False
116+
fermatCheck p r = 1 == moduloPower r (p - 1) p
122117

123118
primality :: Int -> Int -> State LCG Bool
124-
primality p 0 = return True
125-
primality p n = do b <- generate_range 1 p
126-
fermat_check p n (fermat_comp p b)
119+
primality x n = do
120+
rs <- replicateM n (generateRange 1 x)
121+
pure (all (fermatCheck x) rs)
127122
```
128123
:::

exams/finite-automata/index.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ The particular automaton from the figure is defined as follows.
6565
(list 2 3)))
6666
```
6767

68+
### accepts
6869
Implement the function
6970
```racket
7071
(accepts automaton word)
@@ -79,7 +80,8 @@ The function is used as follows:
7980
> (accepts nfa "abab")
8081
#f
8182
```
82-
\noindent
83+
84+
### lwords
8385

8486
Next, given the automaton, its alphabet, and a length, generate the list of all words of the given
8587
length that are accepted by the automaton. Implement the function
@@ -102,12 +104,11 @@ The function operates as follows:
102104
'("aaa" "aba" "abb")
103105
```
104106

105-
For testing purposes your file should be named `task3.rkt` and start with the following lines:
107+
Your file should be named `automata.rkt` and should export the functions `accepts` and `lwords`, and the structs `transition` and `automaton`:
106108
```racket
107109
#lang racket
108110
109-
(provide accepts
110-
lwords)
111+
(provide accepts lwords (struct-out transition) (struct-out automaton))
111112
```
112113

113114
::: details Exam Solution
@@ -202,7 +203,7 @@ nfa = NFA [Tr 1 'a' 2,
202203
[2,3]
203204
```
204205

205-
### `accepts`-function
206+
### accepts
206207
The first part of the task is to decide whether a particular word is accepted by a given automaton.
207208
To that end, implement the function
208209
```haskell
@@ -244,7 +245,7 @@ One more example for `"ba"`:
244245
So the output is `False`.
245246

246247

247-
### `lwords`-function
248+
### lwords
248249

249250
Next, given the automaton, its alphabet, and a length, generate the list of all words of the given
250251
length that are accepted by the automaton. Implement the function
@@ -268,6 +269,16 @@ function operates as follows.
268269
_**Hint:**_ first, generate all possible words of the given length. Then, filter the words using
269270
the function `accepts`.
270271

272+
273+
Your file should be named `Automata.hs` and should export the functions `accepts` and `lwords`, and the types `Transition` and `Automaton`:
274+
```haskell
275+
module Automata (accepts, lwords, Transition (..), Automaton (..)) where
276+
277+
data Transition a b = Tr a b a deriving Show
278+
data Automaton a b = NFA [(Transition a b)] a [a] deriving Show
279+
```
280+
281+
271282
::: details Exam Solution
272283
```haskell
273284
import Control.Monad.State

exams/minesweeper/index.md

Lines changed: 21 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ outline: deep
77
# Minesweeper
88

99
Implement a program to mark the number of mines directy adjacent (horizontally, vertically and
10-
diagonally) to squares on a Minesweeper field.
10+
diagonally) to squares on a rectangular Minesweeper field.
1111

1212

1313
Fields with `.` denote an empty field and `*` denote mines:
@@ -48,10 +48,6 @@ Your file should be called `minesweeper.rkt`. You may assume the input is rectan
4848
The functions `string->list` and `string-split` might be useful to parse the output of the function
4949
`port-lines` which reads from stdin. You can use the following skeleton.
5050
```racket
51-
; for testing
52-
(define test-board
53-
(map string->list (string-split ".*..\n..*.\n**..\n...*\n*...")))
54-
5551
; for converting ints to chars.
5652
(define (int->digit i) (integer->char (+ 48 i)))
5753
@@ -64,12 +60,16 @@ The functions `string->list` and `string-split` might be useful to parse the out
6460
(newline)))
6561
```
6662

63+
### Example
64+
65+
```racket
66+
(define board (map string->list (string-split "·*·*·\n··*··\n··*··\n·····")))
67+
```
68+
6769
::: details Exam Solution
6870
```racket
6971
#lang racket
7072
71-
(define board (map string->list (string-split "·*·*·\n··*··\n··*··\n·····")))
72-
7373
(define (int->digit i)
7474
(integer->char (+ 48 i)))
7575
@@ -109,34 +109,27 @@ The functions `string->list` and `string-split` might be useful to parse the out
109109

110110
## Haskell
111111

112-
To read multiple lines of input in plain Haskell, we have to tell it how many lines to read.
113-
Assume that this will be done by first reading a number and then calling `getLine` the desired
114-
number of times. Implement a function `readInput :: IO [String]` with the following behaviour
115-
```haskell
116-
ghci> readInput
117-
3
118-
...
119-
...
120-
...
121-
["...","...","..."] <-- this is the function output
122-
```
123-
124-
Your file should have the extension `Minesweeper.hs`.
112+
Write a Haskell program called `Minesweeper.hs`, which reads the board from standard input. To get all data from standard input as a string, you can call `getContents`. The resulting string can then be split with the `lines` function.
125113

126114
```haskell
127115
-- for converting ints to chars
128116
import Data.Char (intToDigit)
129117

118+
sweep :: [String] -> [String]
119+
sweep board = board -- implement me !
120+
121+
main = do
122+
input <- getContents
123+
mapM_ putStrLn (sweep (lines input))
124+
```
125+
126+
### Example
127+
128+
```haskell
130129
-- for testing
131130
test_board = ["..."
132131
,".**"
133132
,"..."]
134-
135-
main = do
136-
lines <- readInput
137-
putStrLn "\nSweep Result:"
138-
let sw = sweep lines
139-
mapM_ putStrLn sw
140133
```
141134

142135
::: details Exam Solution
@@ -165,20 +158,8 @@ sweep board = mapi2d pretty board where
165158
mines x y = count (neighbours x y board)
166159
count xs = length $ filter (=='*') xs
167160

168-
readInput :: IO [String]
169-
readInput = do
170-
count <- readLn -- type is infered because of the signature of replicateM
171-
lines <- replicateM (count) getLine
172-
return lines
173-
174-
test_board = ["..."
175-
,".**"
176-
,"..."]
177-
178161
main = do
179-
lines <- readInput
180-
putStrLn "\nSweep Result:"
181-
let sw = sweep lines
182-
mapM_ putStrLn sw
162+
input <- getContents
163+
mapM_ putStrLn (sweep (lines input))
183164
```
184165
:::

0 commit comments

Comments
 (0)