cws/cw02.tex
changeset 48 7a6a75ea9738
parent 46 48d2cbe8ee5e
child 50 9891c9fac37e
equal deleted inserted replaced
46:48d2cbe8ee5e 48:7a6a75ea9738
    76 A knight's tour is called \emph{closed}, if the last step in the tour
    76 A knight's tour is called \emph{closed}, if the last step in the tour
    77 is within a knight's move to the beginning of the tour. So the above
    77 is within a knight's move to the beginning of the tour. So the above
    78 knight's tour is \underline{not} closed (it is open) because the last
    78 knight's tour is \underline{not} closed (it is open) because the last
    79 step on field $(0, 4)$ is not within the reach of the first step on
    79 step on field $(0, 4)$ is not within the reach of the first step on
    80 $(4, 4)$. It turns out there is no closed knight's tour on a $5\times
    80 $(4, 4)$. It turns out there is no closed knight's tour on a $5\times
    81 5$ board. But there are on a $6\times 6$ board, for example
    81 5$ board. But there are on a $6\times 6$ board and bigger, for example
    82 
    82 
    83 \chessboard[maxfield=e5, 
    83 \chessboard[maxfield=e5, 
    84             pgfstyle= {[base,at={\pgfpoint{0pt}{-0.5ex}}]text},
    84             pgfstyle= {[base,at={\pgfpoint{0pt}{-0.5ex}}]text},
    85             text = \small 10, markfield=Z5,
    85             text = \small 10, markfield=Z5,
    86             text = \small  5, markfield=a5,
    86             text = \small  5, markfield=a5,
   128 
   128 
   129 
   129 
   130 \noindent
   130 \noindent
   131 where the 35th move can join up again with the 0th move.
   131 where the 35th move can join up again with the 0th move.
   132 
   132 
   133 If you cannot remember how a knight moved in chess, or never played
   133 If you cannot remember how a knight moves in chess, or never played
   134 chess, below are all potential moves indicated for two knights, one on
   134 chess, below are all potential moves indicated for two knights, one on
   135 field $(2, 2)$ (blue) and another on $(7, 7)$ (red):
   135 field $(2, 2)$ (blue moves) and another on $(7, 7)$ (red moves):
   136 
   136 
   137 
   137 
   138 \chessboard[maxfield=g7,
   138 \chessboard[maxfield=g7,
   139             color=blue!50,
   139             color=blue!50,
   140             linewidth=0.2em,
   140             linewidth=0.2em,
   146             markfields={f5, e6},
   146             markfields={f5, e6},
   147             setpieces={Ng7, Nb2}]
   147             setpieces={Ng7, Nb2}]
   148 
   148 
   149 \subsection*{Part 1 (6 Marks)}
   149 \subsection*{Part 1 (6 Marks)}
   150 
   150 
   151 We will implement the knight's tour problem such that we can change
   151 You are asked to implement the knight's tour problem such that the
   152 quickly the dimension of the chessboard. The fun with this problem is
   152 dimension of the board can be changed.  Therefore most functions will
   153 that even for small chessbord dimensions it has already an incredably
   153 take the dimension as an argument.  The fun with this problem is that
   154 large search space---finding a tour is like finding a needle in a
   154 even for small chessbord dimensions it has already an incredably large
   155 haystack. In the first part we want to see far we get with
   155 search space---finding a tour is like finding a needle in a
   156 exhaustively exploring the complete search space for small dimensions.
   156 haystack. In the first task we want to see far we get with
   157 
   157 exhaustively exploring the complete search space for small
   158 Let us first fix the basic datastructures for the implementation.  A
   158 chessboards.\medskip
   159 \emph{position} (or field) on the chessboard is a pair of integers. A
   159 
   160 \emph{path} is a list of positions. The first (or 0th move) in a path
   160 \noindent
   161 should be the last element in this list; and the last move is the
   161 Let us first fix the basic datastructures for the implementation.  The
   162 first element. For example the path for the $5\times 5$ chessboard
   162 board dimension is an integer (we will never go boyond board sizes of
   163 above is represented by
   163 $100 \times 100$).  A \emph{position} (or field) on the chessboard is
       
   164 a pair of integers, like $(0, 0)$. A \emph{path} is a list of
       
   165 positions. The first (or 0th move) in a path is the last element in
       
   166 this list; and the last move in the path is the first element. For
       
   167 example the path for the $5\times 5$ chessboard above is represented
       
   168 by
   164 
   169 
   165 \[
   170 \[
   166 \texttt{List($\underbrace{\texttt{(0, 4)}}_{24}$,
   171 \texttt{List($\underbrace{\texttt{(0, 4)}}_{24}$,
   167   $\underbrace{\texttt{(2, 3)}}_{23}$, ..., (3, 2), $\underbrace{\texttt{(4, 4)}}_0$)}
   172   $\underbrace{\texttt{(2, 3)}}_{23}$, ...,
       
   173   $\underbrace{\texttt{(3, 2)}}_1$, $\underbrace{\texttt{(4, 4)}}_0$)}
   168 \]
   174 \]
   169 
   175 
   170 \noindent
   176 \noindent
   171 Suppose the dimension of a chessboard is $n$, then a path is a
   177 Suppose the dimension of a chessboard is $n$, then a path is a
   172 \emph{tour} if the length of the path is $n \times n$, each element
   178 \emph{tour} if the length of the path is $n \times n$, each element
   177 \subsubsection*{Tasks (file knight1.scala)}
   183 \subsubsection*{Tasks (file knight1.scala)}
   178 
   184 
   179 \begin{itemize}
   185 \begin{itemize}
   180 \item[(1a)] Implement a is-legal-move function that takes a dimension, a path
   186 \item[(1a)] Implement a is-legal-move function that takes a dimension, a path
   181 and a position as argument and tests whether the position is inside
   187 and a position as argument and tests whether the position is inside
   182 the board and not yet element in the path.
   188 the board and not yet element in the path. \hfill[1 Mark]
   183 
   189 
   184 \item[(1b)] Implement a legal-moves function that calculates for a
   190 \item[(1b)] Implement a legal-moves function that calculates for a
   185   position all legal follow-on moves. If the follow-on moves are
   191   position all legal onward moves. If the onward moves are
   186   placed on a circle, you should produce them starting from
   192   placed on a circle, you should produce them starting from
   187   ``12-oclock'' following in clockwise order.  For example on an
   193   ``12-oclock'' following in clockwise order.  For example on an
   188   $8\times 8$ board for a knight on position $(2, 2)$ and otherwise
   194   $8\times 8$ board for a knight on position $(2, 2)$ and otherwise
   189   empty board, the legal-moves function should produce the follow-on
   195   empty board, the legal-moves function should produce the onward
   190   positions
   196   positions
   191 
   197 
   192   \begin{center}
   198   \begin{center}
   193   \texttt{List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))}
   199   \texttt{List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))}
   194   \end{center}
   200   \end{center}
   195 
   201 
   196   If the board is not empty, then maybe some of the moves need to be filtered out from this list.
   202   in this order.  If the board is not empty, then maybe some of the
   197   For a knight on field $(7, 7)$ and an empty board, the legal moves
   203   moves need to be filtered out from this list.  For a knight on field
   198   are
   204   $(7, 7)$ and an empty board, the legal moves are
   199 
   205 
   200   \begin{center}
   206   \begin{center}
   201   \texttt{List((6,5), (5,6))}
   207   \texttt{List((6,5), (5,6))}
   202   \end{center}  
   208   \end{center}
       
   209   \mbox{}\hfill[1 Mark]
   203 
   210 
   204 \item[(1c)] Implement two recursive functions (count-tours and
   211 \item[(1c)] Implement two recursive functions (count-tours and
   205   enum-tours). They each take a dimension and a path as
   212   enum-tours). They each take a dimension and a path as
   206   arguments. They exhaustively search for \underline{open} tours
   213   arguments. They exhaustively search for \underline{\bf open} tours
   207   starting from the given path. The first function counts all possible
   214   starting from the given path. The first function counts all possible
   208   open tours (there can be none for certain board sizes) and the second
   215   open tours (there can be none for certain board sizes) and the second
   209   collects all open tours in a list of paths.
   216   collects all open tours in a list of paths.\hfill[2 Marks]
   210 \end{itemize}
   217 \end{itemize}
   211 
   218 
   212 \noindent \textbf{Test data:} For the marking, these functions will be
   219 \noindent \textbf{Test data:} For the marking, the functions in (1c)
   213 called with board sizes up to $5 \times 5$. If you only search for
   220 will be called with board sizes up to $5 \times 5$. If you only search
   214 open tours starting from field $(0, 0)$, there are 304 of them. If you
   221 for open tours on $5 \times 5$ board starting from field $(0, 0)$,
   215 try out every field of a $5 \times 5$-board as a starting field and
   222 there are 304 of them. If you try out every field of a $5 \times
   216 add up all open tours, you obtain 1728. A $6\times 6$ board is already
   223 5$-board as a starting field and add up all open tours, you obtain
   217 too large to search exhaustively: the number of open tours on
   224 1728. A $6\times 6$ board is already too large to be searched
   218 $6\times 6$, $7\times 7$ and $8\times 8$ are
   225 exhaustively.\footnote{For your interest, the number of open tours on
   219 
   226   $6\times 6$, $7\times 7$ and $8\times 8$ are 6637920, 165575218320,
   220 \begin{center}
   227   19591828170979904, respectively.}
   221 \begin{tabular}{ll}  
       
   222   $6\times 6$ & 6637920\\
       
   223   $7\times 7$ & 165575218320\\
       
   224   $8\times 8$ & 19591828170979904
       
   225 \end{tabular}
       
   226 \end{center}
       
   227 
   228 
   228 \subsubsection*{Tasks (file knight2.scala)}
   229 \subsubsection*{Tasks (file knight2.scala)}
   229 
   230 
   230 \begin{itemize}
   231 \begin{itemize}
   231 \item[(2a)] Implement a first-function. This function takes a list of
   232 \item[(2a)] Implement a first-function. This function takes a list of
   233   position as argument and produces an optional path. The idea behind
   234   position as argument and produces an optional path. The idea behind
   234   the first-function is as follows:
   235   the first-function is as follows:
   235 
   236 
   236   \[
   237   \[
   237   \begin{array}{lcl}
   238   \begin{array}{lcl}
   238   first(\texttt{Nil}, f) & \dn & \texttt{None}\\  
   239   \textit{first}(\texttt{Nil}, f) & \dn & \texttt{None}\\  
   239   first(x\!::\!xs, f) & \dn & \begin{cases}
   240   \textit{first}(x\!::\!xs, f) & \dn & \begin{cases}
   240     f(x) & \textit{if}\;f(x) \not=\texttt{None}\\
   241     f(x) & \textit{if}\;f(x) \not=\texttt{None}\\
   241     first(xs, f) & \textit{otherwise}\\
   242     \textit{first}(xs, f) & \textit{otherwise}\\
   242                               \end{cases}
   243                               \end{cases}
   243   \end{array}
   244   \end{array}
   244   \]
   245   \]
   245 
   246 
       
   247   \noindent That is, we want to find the first position where the
       
   248   result of $f$ is not \texttt{None}.\newline\mbox{}\hfill[1 Mark]
       
   249   
   246 \item[(2b)] Implement a first-tour function. Using the first-function
   250 \item[(2b)] Implement a first-tour function. Using the first-function
   247   from (2a), search recursively for an open tour. Only use the field
   251   from (2a), search recursively for an open tour.  As there might not
   248   $(0, 0)$ as a starting field of the tour. As there might not be such
   252   be such a tour at all, the first-tour function needs to return an
   249   a tour at all, the first-tour function needs to return an
   253   \texttt{Option[Path]}.\hfill[2 Marks]
   250   \texttt{Option[Path]}. For the marking, this function will be called
   254 \end{itemize}
   251   with board sizes up to $8 \times 8$.
   255 
   252 \end{itemize}  
   256 \noindent
       
   257 \textbf{Testing} The first tour function will be called with board
       
   258 sizes of up to $8 \times 8$. 
   253 
   259 
   254 
   260 
   255 \subsection*{Part 2 (4 Marks)}
   261 \subsection*{Part 2 (4 Marks)}
   256 
   262 
   257 For open tours beyond $8 \times 8$ boards and also for searching for
   263 As you should have seen in Part 1, a naive search for open tours
   258 closed tours, an heuristic (called Warnsdorf's rule) needs to be
   264 beyond $8 \times 8$ boards and also for searching for closed tours
   259 implemented. This rule states that a knight is moved so that it
   265 takes too much time. There is a heuristic (called Warnsdorf's rule)
   260 always proceeds to the square from which the knight will have the
   266 that can speed up finding a tour. This heuristice states that a knight
   261 fewest onward moves.  For example for a knight on field $(1, 3)$,
   267 is moved so that it always proceeds to the square from which the
   262 the field $(0, 1)$ has the fewest possible onward moves.
   268 knight will have the \underline{fewest} onward moves.  For example for
       
   269 a knight on field $(1, 3)$, the field $(0, 1)$ has the fewest possible
       
   270 onward moves, namely 2.
   263 
   271 
   264 \chessboard[maxfield=g7,
   272 \chessboard[maxfield=g7,
   265             pgfstyle= {[base,at={\pgfpoint{0pt}{-0.5ex}}]text},
   273             pgfstyle= {[base,at={\pgfpoint{0pt}{-0.5ex}}]text},
   266             text = \small 3, markfield=Z5,
   274             text = \small 3, markfield=Z5,
   267             text = \small 7, markfield=b5,
   275             text = \small 7, markfield=b5,
   270             text = \small 5, markfield=b1,
   278             text = \small 5, markfield=b1,
   271             text = \small 2, markfield=Z1,
   279             text = \small 2, markfield=Z1,
   272             setpieces={Na3}]
   280             setpieces={Na3}]
   273 
   281 
   274 \noindent
   282 \noindent
   275 Warnsdorf's rule states that the moves sould be tried out in the
   283 Warnsdorf's rule states that the moves on the board above sould be
   276 order
   284 tried out in the order
   277 
   285 
   278 \[
   286 \[
   279 (0, 1), (0, 5), (2, 1), (2, 5), (3, 4), (3, 2)
   287 (0, 1), (0, 5), (2, 1), (2, 5), (3, 4), (3, 2)
   280 \]
   288 \]
   281 
   289