14 hlabelformat=\arabic{ranklabel}, |
15 hlabelformat=\arabic{ranklabel}, |
15 vlabelformat=\arabic{filelabel}} |
16 vlabelformat=\arabic{filelabel}} |
16 |
17 |
17 \mbox{}\\[-18mm]\mbox{} |
18 \mbox{}\\[-18mm]\mbox{} |
18 |
19 |
19 \section*{Coursework 7 (Scala)} |
20 \section*{Coursework 8 (Scala)} |
20 |
21 |
21 This coursework is worth 10\%. It is about searching and |
22 This coursework is worth 10\%. It is about searching and |
22 backtracking. The first part is due on 29 November at 11pm; the |
23 backtracking. The first part is due on 29 November at 11pm; the |
23 second, more advanced part, is due on 20 December at 11pm. You are |
24 second, more advanced part, is due on 20 December at 11pm. You are |
24 asked to implement Scala programs that solve various versions of the |
25 asked to implement Scala programs that solve various versions of the |
25 \textit{Knight's Tour Problem} on a chessboard. Note the second, more |
26 \textit{Knight's Tour Problem} on a chessboard. Note the second, more |
26 advanced, part might include material you have not yet seen in the |
27 advanced, part might include material you have not yet seen in the |
27 first two lectures. \bigskip |
28 first three lectures. \bigskip |
28 |
29 |
29 \IMPORTANT{} |
30 \IMPORTANT{} |
30 Also note that the running time of each part will be restricted to a |
31 Also note that the running time of each part will be restricted to a |
31 maximum of 360 seconds on my laptop: If you calculate a result once, |
32 maximum of 30 seconds on my laptop: If you calculate a result once, |
32 try to avoid to calculate the result again. Feel free to copy any code |
33 try to avoid to calculate the result again. Feel free to copy any code |
33 you need from files \texttt{knight1.scala}, \texttt{knight2.scala} and |
34 you need from files \texttt{knight1.scala}, \texttt{knight2.scala} and |
34 \texttt{knight3.scala}. |
35 \texttt{knight3.scala}. |
35 |
36 |
36 \DISCLAIMER{} |
37 \DISCLAIMER{} |
136 |
137 |
137 If you cannot remember how a knight moves in chess, or never played |
138 If you cannot remember how a knight moves in chess, or never played |
138 chess, below are all potential moves indicated for two knights, one on |
139 chess, below are all potential moves indicated for two knights, one on |
139 field $(2, 2)$ (blue moves) and another on $(7, 7)$ (red moves): |
140 field $(2, 2)$ (blue moves) and another on $(7, 7)$ (red moves): |
140 |
141 |
141 |
142 {\chessboard[maxfield=g7, |
142 \chessboard[maxfield=g7, |
|
143 color=blue!50, |
143 color=blue!50, |
144 linewidth=0.2em, |
144 linewidth=0.2em, |
145 shortenstart=0.5ex, |
145 shortenstart=0.5ex, |
146 shortenend=0.5ex, |
146 shortenend=0.5ex, |
147 markstyle=cross, |
147 markstyle=cross, |
148 markfields={a4, c4, Z3, d3, Z1, d1, a0, c0}, |
148 markfields={a4, c4, Z3, d3, Z1, d1, a0, c0}, |
149 color=red!50, |
149 color=red!50, |
150 markfields={f5, e6}, |
150 markfields={f5, e6}, |
151 setpieces={Ng7, Nb2}] |
151 setpieces={Ng7, Nb2}, |
152 |
152 boardfontsize=12pt,labelfontsize=9pt]} |
153 |
153 |
154 \noindent |
154 \subsection*{Reference Implementation} |
155 \textbf{Hints:} useful list functions: \texttt{.contains(..)} checks |
155 |
|
156 The Scala assignment comes with reference implementations in form of |
|
157 a \texttt{jar}-files. This allows you to run any test cases on your own |
|
158 computer. For example you can call Scala on the command line with the |
|
159 option \texttt{-cp knight1.jar} and then query any function from the |
|
160 template file. |
|
161 |
|
162 \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] |
|
163 $ scala -cp knight1.jar |
|
164 |
|
165 scala> CW8a.enum_tours(5, List((0, 0))).length |
|
166 Time needed: 1.722 secs. |
|
167 res0: Int = 304 |
|
168 |
|
169 scala> CW8a.print_board(8, CW8a.first_tour(8, List((0, 0))).get) |
|
170 Time needed: 15.411 secs. |
|
171 |
|
172 51 46 55 44 53 4 21 12 |
|
173 56 43 52 3 22 13 24 5 |
|
174 47 50 45 54 25 20 11 14 |
|
175 42 57 2 49 40 23 6 19 |
|
176 35 48 41 26 61 10 15 28 |
|
177 58 1 36 39 32 27 18 7 |
|
178 37 34 31 60 9 62 29 16 |
|
179 0 59 38 33 30 17 8 63 |
|
180 \end{lstlisting}%$ |
|
181 |
|
182 |
|
183 \subsection*{Hints} |
|
184 |
|
185 \noindent |
|
186 \textbf{Part 1} useful list functions: \texttt{.contains(..)} checks |
156 whether an element is in a list, \texttt{.flatten} turns a list of |
187 whether an element is in a list, \texttt{.flatten} turns a list of |
157 lists into just a list, \texttt{\_::\_} puts an element on the head of |
188 lists into just a list, \texttt{\_::\_} puts an element on the head of |
158 the list, \texttt{.head} gives you the first element of a list (make |
189 the list, \texttt{.head} gives you the first element of a list (make |
159 sure the list is not \texttt{Nil}). |
190 sure the list is not \texttt{Nil}); a useful option function: |
160 |
191 \texttt{.isDefined} returns true, if an option is \texttt{Some(..)}; |
161 \noindent |
192 anonymous functions can be constructed using \texttt{(x:Int) => ...}, |
162 \textbf{Hints:} a useful list function: \texttt{.sortBy} sorts a list |
193 this functions takes an \texttt{Int} as an argument.\medskip |
|
194 |
|
195 |
|
196 \noindent |
|
197 \textbf{Part 2} a useful list function: \texttt{.sortBy} sorts a list |
163 according to a component given by the function; a function can be |
198 according to a component given by the function; a function can be |
164 tested to be tail recursive by annotation \texttt{@tailrec}, which is |
199 tested to be tail recursive by annotation \texttt{@tailrec}, which is |
165 made available by importing \texttt{scala.annotation.tailrec}. |
200 made available by importing \texttt{scala.annotation.tailrec}. |
166 |
201 |
167 |
202 |
168 \subsection*{Part 1 (7 Marks)} |
203 |
|
204 |
|
205 \subsection*{Part 1 (6 Marks)} |
169 |
206 |
170 You are asked to implement the knight's tour problem such that the |
207 You are asked to implement the knight's tour problem such that the |
171 dimension of the board can be changed. Therefore most functions will |
208 dimension of the board can be changed. Therefore most functions will |
172 take the dimension of the board as an argument. The fun with this |
209 take the dimension of the board as an argument. The fun with this |
173 problem is that even for small chessboard dimensions it has already an |
210 problem is that even for small chessboard dimensions it has already an |
176 with exhaustively exploring the complete search space for small |
213 with exhaustively exploring the complete search space for small |
177 chessboards.\medskip |
214 chessboards.\medskip |
178 |
215 |
179 \noindent |
216 \noindent |
180 Let us first fix the basic datastructures for the implementation. The |
217 Let us first fix the basic datastructures for the implementation. The |
181 board dimension is an integer (we will never go beyond board sizes of |
218 board dimension is an integer. |
182 $40 \times 40$). A \emph{position} (or field) on the chessboard is |
219 A \emph{position} (or field) on the chessboard is |
183 a pair of integers, like $(0, 0)$. A \emph{path} is a list of |
220 a pair of integers, like $(0, 0)$. A \emph{path} is a list of |
184 positions. The first (or 0th move) in a path is the last element in |
221 positions. The first (or 0th move) in a path is the last element in |
185 this list; and the last move in the path is the first element. For |
222 this list; and the last move in the path is the first element. For |
186 example the path for the $5\times 5$ chessboard above is represented |
223 example the path for the $5\times 5$ chessboard above is represented |
187 by |
224 by |
242 there are 304 of tours. If you try out every field of a $5 \times |
279 there are 304 of tours. If you try out every field of a $5 \times |
243 5$-board as a starting field and add up all tours, you obtain |
280 5$-board as a starting field and add up all tours, you obtain |
244 1728. A $6\times 6$ board is already too large to be searched |
281 1728. A $6\times 6$ board is already too large to be searched |
245 exhaustively.\footnote{For your interest, the number of tours on |
282 exhaustively.\footnote{For your interest, the number of tours on |
246 $6\times 6$, $7\times 7$ and $8\times 8$ are 6637920, 165575218320, |
283 $6\times 6$, $7\times 7$ and $8\times 8$ are 6637920, 165575218320, |
247 19591828170979904, respectively.}\bigskip |
284 19591828170979904, respectively.}\smallskip |
248 |
285 |
249 |
286 |
250 |
287 |
251 \subsubsection*{Tasks (file knight2.scala)} |
288 \subsubsection*{Tasks (cont.)} |
252 |
289 |
253 \begin{itemize} |
290 \begin{itemize} |
254 \item[(4)] Implement a \texttt{first}-function. This function takes a list of |
291 \item[(4)] Implement a \texttt{first}-function. This function takes a list of |
255 positions and a function $f$ as arguments; $f$ is the name we give to |
292 positions and a function $f$ as arguments; $f$ is the name we give to |
256 this argument). The function $f$ takes a position as argument and |
293 this argument). The function $f$ takes a position as argument and |
269 |
306 |
270 \noindent That is, we want to find the first position where the |
307 \noindent That is, we want to find the first position where the |
271 result of $f$ is not \texttt{None}, if there is one. Note that |
308 result of $f$ is not \texttt{None}, if there is one. Note that |
272 `inside' \texttt{first}, you do not (need to) know anything about |
309 `inside' \texttt{first}, you do not (need to) know anything about |
273 the argument $f$ except its type, namely \texttt{Pos => |
310 the argument $f$ except its type, namely \texttt{Pos => |
274 Option[Path]}. There is one additional point however you should |
311 Option[Path]}. If you want to find out what the result of $f$ is |
|
312 on a particular argument, say $x$, you can just write $f(x)$. |
|
313 There is one additional point however you should |
275 take into account when implementing \texttt{first}: you will need to |
314 take into account when implementing \texttt{first}: you will need to |
276 calculate what the result of $f(x)$ is; your code should do this |
315 calculate what the result of $f(x)$ is; your code should do this |
277 only \textbf{once} and for as \textbf{few} elements in the list as |
316 only \textbf{once} and for as \textbf{few} elements in the list as |
278 possible! Do not calculate $f(x)$ for all elements and then see which |
317 possible! Do not calculate $f(x)$ for all elements and then see which |
279 is the first \texttt{Some}.\\\mbox{}\hfill[1 Mark] |
318 is the first \texttt{Some}.\\\mbox{}\hfill[1 Mark] |
280 |
319 |
281 \item[(5)] Implement a \texttt{first\_tour} function that uses the |
320 \item[(5)] Implement a \texttt{first\_tour} function that uses the |
282 \texttt{first}-function from (2a), and searches recursively for a tour. |
321 \texttt{first}-function from (4), and searches recursively for single tour. |
283 As there might not be such a tour at all, the \texttt{first\_tour} function |
322 As there might not be such a tour at all, the \texttt{first\_tour} function |
284 needs to return a value of type |
323 needs to return a value of type |
285 \texttt{Option[Path]}.\\\mbox{}\hfill[1 Mark] |
324 \texttt{Option[Path]}.\\\mbox{}\hfill[1 Mark] |
286 \end{itemize} |
325 \end{itemize} |
287 |
326 |
288 \noindent |
327 \noindent |
289 \textbf{Testing:} The \texttt{first\_tour} function will be called with board |
328 \textbf{Testing:} The \texttt{first\_tour} function will be called with board |
290 sizes of up to $8 \times 8$. |
329 sizes of up to $8 \times 8$. |
291 \bigskip |
330 \bigskip |
292 |
331 |
293 \noindent |
|
294 \textbf{Hints:} a useful list function: \texttt{.filter(..)} filters a |
|
295 list according to a boolean function; a useful option function: |
|
296 \texttt{.isDefined} returns true, if an option is \texttt{Some(..)}; |
|
297 anonymous functions can be constructed using \texttt{(x:Int) => ...}, |
|
298 this functions takes an \texttt{Int} as an argument. |
|
299 |
332 |
300 |
333 |
301 %%\newpage |
334 %%\newpage |
302 \subsection*{Part 2 (3 Marks)} |
335 \subsection*{Advanced Part 2 (4 Marks)} |
303 |
336 |
304 As you should have seen in Part 1, a naive search for tours beyond |
337 As you should have seen in Part 1, a naive search for tours beyond |
305 $8 \times 8$ boards and also searching for closed tours even on small |
338 $8 \times 8$ boards and also searching for closed tours even on small |
306 boards takes too much time. There is a heuristic, called \emph{Warnsdorf's |
339 boards takes too much time. There is a heuristic, called \emph{Warnsdorf's |
307 Rule} that can speed up finding a tour. This heuristic states that a |
340 Rule} that can speed up finding a tour. This heuristic states that a |
331 \noindent |
364 \noindent |
332 Whenever there are ties, the corresponding onward moves can be in any |
365 Whenever there are ties, the corresponding onward moves can be in any |
333 order. When calculating the number of onward moves for each field, we |
366 order. When calculating the number of onward moves for each field, we |
334 do not count moves that revisit any field already visited. |
367 do not count moves that revisit any field already visited. |
335 |
368 |
336 \subsubsection*{Tasks (file knight3.scala)} |
369 \subsubsection*{Tasks (file knight2.scala)} |
337 |
370 |
338 \begin{itemize} |
371 \begin{itemize} |
339 \item[(6)] Write a function \texttt{ordered\_moves} that calculates a list of |
372 \item[(6)] Write a function \texttt{ordered\_moves} that calculates a list of |
340 onward moves like in (2) but orders them according to the |
373 onward moves like in (2) but orders them according to the |
341 Warnsdorf’s Rule. That means moves with the fewest legal onward moves |
374 Warnsdorf’s Rule. That means moves with the fewest legal onward moves |
342 should come first (in order to be tried out first). \hfill[1 Mark] |
375 should come first (in order to be tried out first). \hfill[1 Mark] |
343 |
376 |
344 \item[(7)] Implement a \texttt{first\_closed-tour\_heuristic} |
377 \item[(7)] Implement a \texttt{first\_closed\_tour\_heuristic} |
345 function that searches for a |
378 function that searches for a single |
346 \textbf{closed} tour on a $6\times 6$ board. It should use the |
379 \textbf{closed} tour on a $6\times 6$ board. It should try out |
347 \texttt{first}-function from (4) and tries out onward moves according to |
380 onward moves according to |
348 the \texttt{ordered\_moves} function from (3a). It is more likely to find |
381 the \texttt{ordered\_moves} function from (6). It is more likely to find |
349 a solution when started in the middle of the board (that is |
382 a solution when started in the middle of the board (that is |
350 position $(dimension / 2, dimension / 2)$). \hfill[1 Mark] |
383 position $(dimension / 2, dimension / 2)$). \hfill[1 Mark] |
351 |
384 |
352 \item[(8)] Implement a \texttt{first\_tour\_heuristic} function |
385 \item[(8)] Implement a \texttt{first\_tour\_heuristic} function |
353 for boards up to |
386 for boards up to |
354 $40\times 40$. It is the same function as in (7) but searches for |
387 $30\times 30$. It is the same function as in (7) but searches for |
355 tours (not just closed tours). You have to be careful to write a |
388 tours (not just closed tours). It might be called with any field on the |
356 tail-recursive function of the \texttt{first\_tour\_heuristic} function |
389 board as start.\\ |
357 otherwise you will get problems with stack-overflows.\\ |
390 %You have to be careful to write a |
|
391 %tail-recursive function of the \texttt{first\_tour\_heuristic} function |
|
392 %otherwise you will get problems with stack-overflows.\\ |
|
393 \mbox{}\hfill[1 Mark] |
|
394 \end{itemize} |
|
395 |
|
396 \subsubsection*{Task (file knight3.scala)} |
|
397 \begin{itemize} |
|
398 \item[(9)] Implement a function \texttt{tour\_on\_mega\_board} which is |
|
399 the same function as (7), \textbf{but} can deal with boards up to |
|
400 $70\times 70$ \textbf{within 30 seconds}. This will be tested |
|
401 by starting from field $(0, 0)$. You have to be careful to |
|
402 write a tail-recursive function otherwise you will get problems |
|
403 with stack-overflows. Please observe the requirements about |
|
404 the submissions: no tricks involving \textbf{.par}.\medskip |
|
405 |
|
406 The timelimit of 30 secs is with respect to the laptop on which the |
|
407 marking will happen. You can estimate how well your |
|
408 implementation performs by running \texttt{knight3.jar} on your |
|
409 computer. For example: |
|
410 |
|
411 \begin{lstlisting}[language={},numbers=none,basicstyle=\ttfamily\small] |
|
412 $ scala -cp knight3.jar |
|
413 |
|
414 scala> CW8c.tour_on_mega_board(70, List((0, 0))) |
|
415 Time needed: 9.484 secs. |
|
416 ...<<long_list>>... |
|
417 \end{lstlisting}%$ |
|
418 |
358 \mbox{}\hfill[1 Mark] |
419 \mbox{}\hfill[1 Mark] |
359 \end{itemize} |
420 \end{itemize} |
360 \bigskip |
421 \bigskip |
361 |
422 |
362 |
423 |