% Filename: ChessSetList.lhs % Version : 1.4 % Date : 3/4/92 \section{Building Chess Boards Out Of Lists.} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%M O D U L E%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Lots of data abstraction is used in this version of the knights tour. The searching mechanism can be either a sequential depth first search, or a data parallel search (for instance wedge first??). This module abstracts data type specific operations used in the Heuristic part of the tour. \begin{code} module ChessSetList(Tile, ChessSet, createBoard, sizeBoard, addPiece, deleteFirst, noPieces, positionPiece, lastPiece, firstPiece, pieceAtTile, isSquareFree ) where \end{code} %%%%%%%%%%%%%%%%%% I M P O R T S / T Y P E D E F S %%%%%%%%%%%%%% @Tile@ is a type synonym that represents the $(x,y)$ coordinates of a tile on chess board. The chess board is represented as an algebraic data type\footnote{And hence we can include it in class @Text@, making it @show@able} of an : \begin{itemize} \item {\tt Int} representing the size of the chess board. \item {\tt Int} representing the current move number. \item {\tt Tile} representing the first move of the knight. \item {\tt [Tile]} representing the trail of the knights moves, where the $n^{th}$ tile from the back of the list represents the $n^{th}$ move. \end{itemize} We include information in this type that could of been deduced from the trail alone, but adding the information prevents unnecessary traversal of the trail. \begin{code} import Sort(quickSort) type Tile = (Int,Int) data ChessSet = Board Int Int Tile [Tile] \end{code} %%%%%%%%%%%%%%%%%%%% C L A S S I N S T A N C E S %%%%%%%%%%%%%%%%%%% Various instance declarations for @show@ , @==@ and @<=@. Note the little hack with ordinals, we do not want to compare chess sets, but if we have for instance a tuple of @(Int,ChessSet)@, then we want to compare on the @Int@ part of the tuple. Therefore {\em any} @ChessSet@ is smaller than any other. \begin{code} instance Eq ChessSet where _ == _ = True instance Ord ChessSet where _ <= _ = True instance Show ChessSet where showsPrec p board@(Board sze n f ts) = showString (printBoard sze sortedTrail 1) where sortedTrail = quickSort (assignMoveNo ts sze n) \end{code} %%%%%%%%%%%%%%%%%%%%% B O D Y O F M O D U L E %%%%%%%%%%%%%%%%%%%%% \begin{code} createBoard::Int -> Tile -> ChessSet createBoard x t= Board x 1 t [t] sizeBoard::ChessSet -> Int sizeBoard (Board s _ _ _) = s noPieces::ChessSet -> Int noPieces (Board _ n _ _) = n addPiece::Tile -> ChessSet -> ChessSet addPiece t (Board s n f ts) = Board s (n+1) f (t:ts) \end{code} @deletePiece@ deletes the $x^{th}$ piece placed on the board, and depending on the representation ensures the remaining trail is valid (i.e info reguarding position in valid). \begin{code} deleteFirst::ChessSet -> ChessSet deleteFirst (Board s n f ts) = Board s (n-1) (last ts') ts' where ts' = init ts positionPiece::Int -> ChessSet -> Tile positionPiece x (Board _ n _ ts) = ts !! (n - x) lastPiece::ChessSet -> Tile lastPiece (Board _ _ _ (t:ts)) = t firstPiece::ChessSet -> Tile firstPiece (Board _ _ f _) = f pieceAtTile::Tile -> ChessSet -> Int pieceAtTile x (Board _ _ _ ts) = find x ts where find x [] = error "Tile not used" find x (y:xs) | x == y = 1 + length xs | otherwise = find x xs isSquareFree::Tile -> ChessSet -> Bool isSquareFree x (Board _ _ _ ts) = x `notElem` ts \end{code} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% M I S C %%%%%%%%%%%%%%%%%%%%%%%%%%%%%% Various auxiliary functions used above which I would of liked to include in @where@ clauses if they were not so large. \begin{code} assignMoveNo [] size x = [] assignMoveNo ((x,y):t) size z =(((y-1)*size)+x,z):assignMoveNo t size (z-1) printBoard s [] n | (n > (s*s)) = "" | (n `mod` s /=0)= "*"++(spaces (s*s) 1) ++(printBoard s [] (n+1)) | (n `mod` s ==0)= "*\n" ++(printBoard s [] (n+1)) printBoard s trail@((i,j):xs) n | (i==n) && (n `mod` s ==0)= (show j)++"\n"++(printBoard s xs (n+1)) | (i==n) && (n `mod` s /=0)= (show j)++(spaces (s*s) j)++(printBoard s xs (n+1)) | (n `mod` s /=0)= "*" ++(spaces (s*s) 1)++(printBoard s trail (n+1)) | (n `mod` s ==0)= "*\n" ++(printBoard s trail (n+1)) spaces s y = take ((logTen s) - (logTen y) + 1) [' ',' '..] where logTen 0 = 0 logTen x = 1+ logTen (x `div` 10) \end{code}