3. 0 = otherwise Figure (b) contains the adjacency matrix of the graph G in Figure (a) where the vertices are ordered A, B, C,D, E. Observe that each edge {vi, vj} of G is represented twice, by aij = 1 and aji = 1. Thus, in particular,the adjacency matrix is symmetric.<br />The adjacency matrix A of a graph G does depend on the ordering of the vertices of G, that is, a different ordering of the vertices yields a different adjacency matrix. However, any two such adjacency matrices are closely related in that one can be obtained from the other by simply interchanging row* and columns. On the other hand, the adjacency matrix does not depend on the order in which the edges (pairs of vertices) are input into the computer.<br />There are variations of the above representation. If G is a multigraph, then we usually let denote the number of edges {vi vj}. Moreover,if G is a weighted graph, then we may let, aij denote the weight of the edge {vi, vj}.<br />Consider a directed graph with n vertices, . The simplest graph representation scheme uses an matrix A of zeroes and ones given by <br />That is, the element of the matrix, is a one only if is an edge in G. The matrix A is called an adjacency matrix . <br />For example, the adjacency matrix for graph in Figure is <br />Clearly, the number of ones in the adjacency matrix is equal to the number of edges in the graph. <br />One advantage of using an adjacency matrix is that it is easy to determine the sets of edges emanating from a given vertex. For example, consider vertex . Each one in the row corresponds to an edge that emanates from vertex. Conversely, each one in the column corresponds to an edge incident on vertex. <br />We can also use adjacency matrices to represent undirected graphs. That is, we represent an undirected graph with n vertices, using an matrix A of zeroes and ones given by <br />Since the two sets and are equivalent, matrix A is symmetric about the diagonal. That is, . Furthermore, all of the entries on the diagonal are zero. That is, for . <br />For example, the adjacency matrix for graph in Figure is <br />In this case, there are twice as many ones in the adjacency matrix as there are edges in the undirected graph. <br />A simple variation allows us to use an adjacency matrix to represent an edge-labeled graph. For example, given numeric edge labels, we can represent a graph (directed or undirected) using an matrix A in which the is the numeric label associated with edge in the case of a directed graph, and edge , in an undirected graph. <br />For example, the adjacency matrix for the graph in Figure is <br />In this case, the array entries corresponding to non-existent edges have all been set to . Here serves as a kind of sentinel. The value to use for the sentinel depends on the application. For example, if the edges represent routes between geographic locations, then a route of length is much like one that does not exist. <br />Since the adjacency matrix has entries, the amount of spaced needed to represent the edges of a graph is , regardless of the actual number of edges in the graph. If the graph contains relatively few edges, e.g., if , then most of the elements of the adjacency matrix will be zero (or ). A matrix in which most of the elements are zero (or ) is a sparse matrix. <br />WARSHALL’S ALGORITHM<br />In computer science, the Floyd–Warshall algorithm (sometimes known as the WFI Algorithm[clarification needed] or Roy–Floyd algorithm) is a graph analysis algorithm for finding shortest paths in a weighted graph (with positive or negative edge weights). A single execution of the algorithm will find the lengths (summed weights) of the shortest paths between all pairs of vertices though it does not return details of the paths themselves. The algorithm is an example of dynamic programming. It was published in its currently recognized form by Robert Floyd in 1962. However, it is essentially the same as algorithms previously published by Bernard Roy in 1959 and also by Stephen Warshall in 1962.<br />The Floyd–Warshall algorithm compares all possible paths through the graph between each pair of vertices. It is able to do this with only Θ(V3) comparisons in a graph. This is remarkable considering that there may be up to Ω(V2) edges in the graph, and every combination of edges is tested. It does so by incrementally improving an estimate on the shortest path between two vertices, until the estimate is optimal.<br />Consider a graph G with vertices V, each numbered 1 through N. Further consider a function shortestPath(i, j, k) that returns the shortest possible path from i to j using vertices only from the set {1,2,...,k} as intermediate points along the way. Now, given this function, our goal is to find the shortest path from each i to each j using only vertices 1 to k + 1.<br />There are two candidates for each of these paths: either the true shortest path only uses vertices in the set {1, ..., k}; or there exists some path that goes from i to k + 1, then from k + 1 to j that is better. We know that the best path from i to j that only uses vertices 1 through k is defined by shortestPath(i, j, k), and it is clear that if there were a better path from i to k + 1 to j, then the length of this path would be the concatenation of the shortest path from i to k + 1 (using vertices in {1, ..., k}) and the shortest path from k + 1 to j (also using vertices in {1, ..., k}).<br />Therefore, we can define shortestPath(i, j, k) in terms of the following recursive formula:<br />This formula is the heart of the Floyd–Warshall algorithm. The algorithm works by first computing shortestPath(i, j, k) for all (i, j) pairs for k = 1, then k = 2, etc. This process continues until k = n, and we have found the shortest path for all (i, j) pairs using any intermediate vertices.<br />Conveniently, when calculating the kth case, one can overwrite the information saved from the computation of k − 1. This means the algorithm uses quadratic memory. Be careful to note the initialization conditions:<br /> 1 /* Assume a function edgeCost(i,j) which returns the cost of the edge from i to j<br /> 2 (infinity if there is none).<br /> 3 Also assume that n is the number of vertices and edgeCost(i,i) = 0<br /> 4 */<br /> 5<br /> 6 int path[][];<br /> 7 /* A 2-dimensional matrix. At each step in the algorithm, path[i][j] is the shortest path<br /> 8 from i to j using intermediate vertices (1..k−1). Each path[i][j] is initialized to<br /> 9 edgeCost(i,j) or infinity if there is no edge between i and j.<br />10 */<br />11<br />12 procedure FloydWarshall ()<br />13 for k := 1 to n<br />14 for i := 1 to n<br />15 for j := 1 to n<br />16 path[i][j] = min ( path[i][j], path[i][k]+path[k][j] );<br />The Floyd–Warshall algorithm typically only provides the lengths of the paths between all pairs of vertices. With simple modifications, it is possible to create a method to reconstruct the actual path between any two endpoint vertices. While one may be inclined to store the actual path from each vertex to each other vertex, this is not necessary, and in fact, is very costly in terms of memory. For each vertex, one need only store the information about which vertex one has to go through if one wishes to end up at any given vertex. Therefore, information to reconstruct all paths can be stored in an single N×N matrix 'next' where next[i][j] represents the vertex one must travel through if one intends to take the shortest path from i to j. Implementing such a scheme is trivial as when a new shortest path is found between two vertices, the matrix containing the paths is updated. The next matrix is updated along with the path matrix such that at completion both tables are complete and accurate, and any entries which are infinite in the path table will be null in the next table. The path from i to j is then path from i to next[i][j], followed by path from next[i][j] to j. These two shorter paths are determined recursively. This modified algorithm runs with the same time and space complexity as the unmodified algorithm.<br /> 1 procedure FloydWarshallWithPathReconstruction ()<br /> 2 for k := 1 to n<br /> 3 for i := 1 to n<br /> 4 for j := 1 to n<br /> 5 if path[i][k] + path[k][j] < path[i][j] then<br /> 6 path[i][j] := path[i][k]+path[k][j];<br /> 7 next[i][j] := k;<br /> 8<br /> 9 procedure GetPath (i,j)<br />10 if path[i][j] equals infinity then<br />11 return quot;
no pathquot;
;<br />12 int intermediate := next[i][j];<br />13 if intermediate equals 'null' then<br />14 return quot;
quot;
; /* there is an edge from i to j, with no vertices between */<br />15 else<br />16 return GetPath(i,intermediate) + intermediate + GetPath(intermediate,j);<br />Applications and generalizations<br />The Floyd–Warshall algorithm can be used to solve the following problems, among others:<br />Shortest paths in directed graphs (Floyd's algorithm).<br />Transitive closure of directed graphs (Warshall's algorithm). In Warshall's original formulation of the algorithm, the graph is unweighted and represented by a Boolean adjacency matrix. Then the addition operation is replaced by logical conjunction (AND) and the minimum operation by logical disjunction (OR).<br />Finding a regular expression denoting the regular language accepted by a finite automaton (Kleene's algorithm)<br />Inversion of real matrices (Gauss–Jordan algorithm).<br />Optimal routing. In this application one is interested in finding the path with the maximum flow between two vertices. This means that, rather than taking minima as in the pseudocode above, one instead takes maxima. The edge weights represent fixed constraints on flow. Path weights represent bottlenecks; so the addition operation above is replaced by the minimum operation.<br />Testing whether an undirected graph is bipartite.<br />Fast computation of Pathfinder networks.<br />Maximum Bandwidth Paths in Flow Networks<br />MINIMUM DISTANCES IN WEIGHTED GRAPHS<br />Given a connected, undirected graph, a spanning tree of that graph is a subgraph which is a tree and connects all the vertices together. A single graph can have many different spanning trees. We can also assign a weight to each edge, which is a number representing how unfavorable it is, and use this to assign a weight to a spanning tree by computing the sum of the weights of the edges in that spanning tree. A minimum spanning tree (MST) or minimum weight spanning tree is then a spanning tree with weight less than or equal to the weight of every other spanning tree. More generally, any undirected graph (not necessarily connected) has a minimum spanning forest, which is a union of minimum spanning trees for its connected components.<br />One example would be a cable TV company laying cable to a new neighborhood. If it is constrained to bury the cable only along certain paths, then there would be a graph representing which points are connected by those paths. Some of those paths might be more expensive, because they are longer, or require the cable to be buried deeper; these paths would be represented by edges with larger weights. A spanning tree for that graph would be a subset of those paths that has no cycles but still connects to every house. There might be several spanning trees possible. A minimum spanning tree would be one with the lowest total cost.<br />Weighted Graph<br />We can add attributes to edges. We call the attributes weights. For example if we are using the graph as a map where the vertices are the cites and the edges are highways between the cities. <br />Then if we want the shortest travel distance between cities an appropriate weight would be the road mileage. <br />If we are concerned with the dollar cost of a trip and went the cheapest trip then an appropriate weight for the edges would be the cost to travel between the cities. <br />In both examples we want the shortest trip in terms of the edge-weights. In other words if we designate the weights of the edges as: <br /> w( (vi , vi+1) )<br /> The length of a path, P, is<br /> w(P) = ∑ w((vi , vi+1)) for all edges in P<br /> We call the distance between u and v, d(u, v) = min w(P) for all paths between u and v. <br />Note weights can be negative. Then if a negative weight edge is in a cycle of the graph, we could make the distance between two vertices as negative as we want by cycling many times through the cycle. This would generate an unrealistic answer or cause the algorithm to never exit. So in the case of negative weighted edges we have to be careful.<br />Optimization and Greedy Algorithms<br />Our goal is find the shortest distance from an initial vertex, v, to each vertices of the graph. (This is not the traveling sales man problem.) This is an optimization problem. An optimization problem is a problem where we have a goal to achieve but we also want to achieve the goal at a minimum cost. We want the best solution if there are many solutions to the problem we want the solution that gives the minimum cost. We can also optimize for maximum benefit. For example if some one paid us to go from city to city then naturally we would want the path that paid us the most. Optimization is a typical class of problem for computer scientist. <br />An algorithm that sometimes can solve optimization problems is the Greedy Algorithm. In the greedy algorithm we make several small steps to our goal and at each step we choose the optimal step, greedy-choice. The solution is built from these small steps with local optimal solutions. The greedy algorithm is not guaranteed to give us the optimal solution, if a global optimal solution can be found using a greedy algorithm then we say that the problem posses the greedy choice property. <br />Dijkstra's Algorithm for shortest distance<br />We perform a weighted-breath-first search from the start vertex, v, calculating our best guess distance for each adjacent vertex. The vertex with the smallest distant is assured to have the correct distance. So we can improve our guess of all the vertices adjacent to the vertex with the minimum distance. <br />The author calls relaxation the process for improving the guess. He suggests that a metaphor for remembering the term relaxation is spring. Our initial guess in this case are too large, or the spring is stretched. Then the improvements make the guess/estimate smaller, or the spring relaxes to it proper shape. <br />For algorithm we let D(u) represent our estimate of the distance u from v. (When the algorithm is done D will contain the correct distance.) Initialize D to <br />D(v) = 0 D(u) = inf for u != v<br /> <br />Note that the distance is correct for v. We can improve D for node adjacent to v by edge relaxation: <br /> <br />Edge Relaxation: <br /> <br />if (D(u) + w((u, z) ) < D(z) then D(z) = D(u) + w( (u, z) )<br /> <br />We then add to the cloud the vertex with the smallest guess for the distance. We will want to keep a priority queue Q of the vertices not in the cloud. <br />Algorithm: ShortestPath(G, v) // a little miss leading since the output is only the distance <br />input: A simple undirected weighted graph G <br />with non negative edge weights and a start vertex, v. <br />output: D(u) the distance u is from v. <br />Initialize D(v) = 0 and D(u) = inf for u != v Initialize priority queue Q of all vertices in G using D as the key. while Q is not empty do <br />u = Q.removeMin() for each vertex z adjacent to u and in Q do <br />if D(u) + w((u, z)) < D(z) then <br /> D(z) = D(u) + w((u, z)) <br /> update z in Q<br />return D<br />Note how the use of the priority queue makes the algorithm quite easy to understand and implement. <br />The running time of algorithm depends on the graph, G, and priority queue, Q, implementation. We assume that G is implemented by adjacency list structure. This allows us to update D by iterating through the adjacent vertices of u in time O(degree(u)). <br />Implementing the priority queue, Q, with a heap makes removal efficient O(lg n) where n is the number of vertices in G. If also keep a locater data type which gives us the location of item in the priory queue in O(1), for example and additional reference, locater, kept with the item = (key, element). The location reference is the Position in the heap. If we did not have the locater then search through the heap for the adjacent vertex would take O(n) instead of O(1) as with the locater. Then when we insert an item we get the location returned and can access the item in the heap using the locater. We can update the D for the adjacent vertex in O(degree(u) lg n) the time. <br />EULERIAN AND HAMILTONIAN CIRCUITS<br />In graph theory, an Eulerian path is a path in a graph which visits each edge exactly once. Similarly, an Eulerian circuit is an Eulerian path which starts and ends on the same vertex. They were first discussed by Leonhard Euler while solving the famous Seven Bridges of Königsberg problem in 1736. Mathematically the problem can be stated like this:<br />Euler proved that a necessary condition for the existence of Eulerian circuits is that all vertices in the graph have an even degree, and stated without proof that connected graphs with all vertices of even degree have an Eulerian circuit. The first complete proof of this latter claim was published in 1873 by Carl Hierholzer.<br />The term Eulerian graph has two common meanings in graph theory. One meaning is a graph with an Eulerian circuit, and the other is a graph with every vertex of even degree. These definitions coincide for connected graphs.<br />For the existence of Eulerian paths it is necessary that no more than two vertices have an odd degree; this means the Königsberg graph is not Eulerian. If there are no vertices of odd degree, all Eulerian paths are circuits. If there are exactly two vertices of odd degree, all Eulerian paths start at one of them and end at the other. Sometimes a graph that has an Eulerian path, but not an Eulerian circuit (in other words, it is an open path, and does not start and end at the same vertex) is called semi-Eulerian.<br />Constructing Eulerian paths and circuits<br />Consider a graph known to have all edges in the same component and at most two vertices of odd degree. We can construct an Eulerian path out of this graph by using Fleury's algorithm, which dates to 1883. We start with a vertex of odd degree—if the graph has none, then start with any vertex. At each step we move across an edge whose deletion would not disconnect the graph, unless we have no choice, then we delete that edge. At the end of the algorithm there are no edges left, and the sequence of edges we moved across forms an Eulerian cycle if the graph has no vertices of odd degree; or an Eulerian path if there are exactly two vertices of odd degree.<br />Special cases<br />The asymptotic formula for the number of Eulerian circuits in the complete graphs was determined by McKay and Robinson (1995):[8]<br />A similar formula was later obtained by M.I. Isaev (2009) for complete bipartite graphs:[9]<br />A.Eulerian Graph<br />An Eulerian graph is as graph containing an Eulerian cycle. The numbers of Eulerian graphs with , 2, ... nodes are 1, 0, 1, 1, 4, 8, 37, 184, 1782, ... (Sloane's A003049; Robinson 1969; Liskovec 1972; Harary and Palmer 1973, p. 117). <br />Some care is needed in interpreting this term, however, since some authors define an Euler graph as a different object, namely a graph for which all vertices are of even degree (motivated by the following theorem). <br />Euler showed (without proof) that a connected simple graph is Eulerian iff it has no graph vertices of odd degree (i.e., all vertices are of even degree). The number of connected Euler graphs on nodes is therefore equal to the number of Eulerian graphs on nodes. <br />A directed graph is Eulerian iff every graph vertex has equal indegree and outdegree. A planar bipartite graph is dual to a planar Eulerian graph and vice versa. The numbers of Eulerian digraphs on , 2, ... nodes are 1, 1, 3, 12, 90, 2162, ... (Sloane's A058337). <br />Finding the largest subgraph of graph having an odd number of vertices which is Eulerian is an NP-complete problem (Skiena 1990, p. 194). <br />B.Hamiltonian path<br />A Hamiltonian graph, also called a Hamilton graph, is a graph possessing a Hamiltonian cycle. A graph that is not Hamiltonian is said to be nonhamiltonian. <br />While it would be easy to make a general definition of quot;
Hamiltonianquot;
that goes either way as far as the singleton graph is concerned, defining quot;
Hamiltonianquot;
to mean quot;
has a Hamiltonian cyclequot;
and taking quot;
Hamiltonian cyclesquot;
to be a subset of quot;
cyclesquot;
in general would lead to the convention that the singleton graph is nonhamiltonian (B. McKay, pers. comm., Oct. 11, 2006). However, by convention, the singleton graph is generally considered to be Hamiltonian (B. McKay, pers. comm., Mar. 22, 2007). The convention in this work and in GraphData is that is Hamiltonian, while is nonhamiltonian. <br />The numbers of simple Hamiltonian graphs on nodes for , 2, ... are then given by 1, 0, 1, 3, 8, 48, 383, 6196, 177083, ... (Sloane's A003216). <br />A graph can be tested to see if it is Hamiltonian using the command HamiltonianQ[g] in the Mathematica package Combinatorica` . <br />Testing whether a graph is Hamiltonian is an NP-complete problem (Skiena 1990, p. 196). Rubin (1974) describes an efficient search procedure that can find some or all Hamilton paths and circuits in a graph using deductions that greatly reduce backtracking and guesswork. <br />All Hamiltonian graphs are biconnected, although the converse is not true (Skiena 1990, p. 197). Any bipartite graph with unbalanced vertex parity is not Hamiltonian. <br />If the sums of the degrees of nonadjacent vertices in a graph is greater than the number of nodes for all subsets of nonadjacent vertices, then is Hamiltonian (Ore 1960; Skiena 1990, p. 197). <br />All planar 4-connected graphs have Hamiltonian cycles, but not all polyhedral graphs do. For example, the smallest polyhedral graph that is not Hamiltonian is the Herschel graph on 11 nodes. <br />19050001326515In the mathematical field of graph theory, a Hamiltonian path (or traceable path) is a path in an undirected graph which visits each vertex exactly once. A Hamiltonian cycle (or Hamiltonian circuit) is a cycle in an undirected graph which visits each vertex exactly once and also returns to the starting vertex. Determining whether such paths and cycles exist in graphs is the Hamiltonian path problem which is NP-complete.<br /> <br /> <br />A Hamiltonian cycle in a dodecahedron<br />20288251162050Hamiltonian paths and cycles are named after William Rowan Hamilton who invented the Icosian game, now also known as Hamilton's puzzle, which involves finding a Hamiltonian cycle in the edge graph of the dodecahedron. Hamilton solved this problem using the Icosian Calculus, an algebraic structure based on roots of unity with many similarities to the quaternions (also invented by Hamilton). This solution does not generalize to arbitrary graphs.<br />A Hamiltonian path (black) over a graph<br />All Platonic solids are Hamiltonian (Gardner 1957), as illustrated above. <br />Although not explicitly stated by Gardner (1957), all Archimedean solids have Hamiltonian circuits as well, several of which are illustrated above.<br /> Two points are called adjacent if there is an edge connecting them. <br /> Euler path and circuit. If it is possible to start at a vertex and move along each path so as to pass along each edge without going over any of them more than once the graph has an Euler path. If the path ends at the same vertex at which you started it is called an Euler circuit. Some nice problems, explanations, and illustrations are shown at Isaac Reed's wonderful web site. Even some very simple graphs like the one above do not have an Euler path (try it). The reason can be found at the web site just mentioned.<br /> Hamiltonian Circuit a Hamiltonian circuit, named for Irish mathematician Sir William Rowan Hamilton, is a circuit (a path that ends where it starts) that visits each vertex once without touching any vertex more than once. There may be more than one Hamilton path for a graph, and then we often wish to solve for the shortest such path. This is often referred to as a traveling salesman or postman problem. Every complete graph (n>2) has a Hamilton circuit. <br />KNIGHT’S TOUR (64 SQUARES)<br />The Knight's Tour is a mathematical problem involving a knight on a chessboard. The knight is placed on the empty board and, moving according to the rules of chess, must visit each square exactly once. A knight's tour is called a closed tour if the knight ends on a square attacking the square from which it began (so that it may tour the board again immediately with the same path). Otherwise the tour is open. The exact number of open tours is still unknown. Creating a program to solve the knight's tour is a common problem given to computer science students.[1] Variations of the knight's tour problem involve chessboards of different sizes than the usual 8 × 8, as well as irregular (non-rectangular) boards.<br />The knight's tour problem is an instance of the more general Hamiltonian path problem in graph theory. The problem of finding a closed knight's tour is similarly an instance of the hamiltonian cycle problem. Note however that, unlike the general Hamiltonian path problem, the knight's tour problem can be solved in linear time.[2]<br />The earliest known references to the Knight's Tour problem date back to the 9th century CE. The pattern of a knight's tour on a half-board has been presented in verse form (as a literary constraint) in the highly stylized Sanskrit poem Kavyalankara written by the 9th century Kashmiri poet Rudrata, which discusses the art of poetry, especially with relation to theater (Natyashastra). As was often the practice in ornate Sanskrit poetry, the syllabic patterns of this poem elucidate a completely different motif, in this case an open knight's tour on a half-chessboard.<br />One of the first mathematicians to investigate the knight's tour was Leonhard Euler. The first algorithm for completing the Knight's Tour was Warnsdorff's algorithm, first described in 1823 by H. C. Warnsdorff.<br />In the 20th century the Oulipo group of writers used it among many others. The most notable example is the 10 × 10 Knight's Tour which sets the order of the chapters in Georges Perec's novel Life: A User's Manual. The sixth game of the 2010 World Chess Championship between Viswanathan Anand and Veselin Topalov saw Anand making 13 consecutive knight moves.<br />The Knight's Tour problem is the problem of finding a Hamilton cycle (closed loop) for a knight traversing a chess board in the standard manner.<br />This problem is easily implemented as a simple backtracking-based depth-first-search algorithm. We maintain a list of visited squares, visited, and at each iteration we perform the following algorithm to progress from the current square: <br />3314700-228600Find the list of moves available to us <br />If there are none, return visited if it is a valid solution (isSolution) <br />Otherwise, try the moves available to us, collecting solutions using the list monad <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:solutionsquot;
solutions>>=<br />import Data.List (())<br />solutions :: (Int,Int) -> [(Int,Int)] -> [[(Int,Int)]]<br />solutions square visited = <br /> case nextMoves square visited of<br /> [] -> filter isSolution (return (reverse (square : visited)))<br /> moves -><br /> do move <- moves<br /> solutions move (square : visited)<br />Squares are represented as 1-based pairs of x and y co-ordinates, ie. a full board is: [(x,y) | x <- [1..8] , y <- [1..8]]. <br />The list of available moves is found by determining all the moves available to us (nextMoves square), then filtering then to remove those we have visited using visited ( is the set difference operator). <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:nextMovesquot;
nextMoves>>=<br />nextMoves :: (Int,Int) -> [(Int,Int)]<br />nextMoves (x,y) = <br /> [(x',y') | <br /> (x',y') <- [(x + 1,y + 2),(x + 1, y - 2),<br /> (x - 1,y + 2),(x - 1, y - 2),<br /> (x + 2,y + 1),(x + 2, y - 1),<br /> (x - 2,y + 1),(x - 2, y - 1)],<br /> 1 <= x' && x' <= 8 && 1 <= y' && y' <= 8]<br />Knight's graph showing all possible paths for a Knight's tour on a standard 8×8 chessboard. The numbers on each node indicate the number of possible moves that can be made from that position.<br />Conversions <br />The following functions convert between the two systems: <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:conversionsquot;
conversions>>=<br />fromSquare :: (Int,Int) -> Int<br />fromSquare (x,y) = (x + y * 8 - 9)<br />toSquare :: Int -> (Int,Int)<br />toSquare x = (r+1, q+1)<br /> where (q,r) = x `divMod` 8<br />Writing squares as integers, we now look at the types of the operations we would like to perform, namely: <br />Visit a square: addSquare :: Int -> a -> a <br />Check if we're done: isEmpty :: a -> Bool <br />Filter the list of moves: filterList :: b -> a -> b <br />The question is: what is required of our type a? It must: <br />Quickly determine membership for an integer between 0 and 63 <br />Determine whether no integers between 0 and 63 are members <br />Filter a list of moves, of type b <br />A.A Knight's Tour using words <br />It is easy to observe that these are simply bit operations, on a 64-bit word! We therefore maintain a 64-bit word representing available moves. <br />We can therefore rewrite solutions, to solutionsF: <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:solutionsFquot;
solutionsF>>=<br />solutionsF :: Bits a => Int -> a -> [Int] -> [[(Int,Int)]]<br />solutionsF square visited list =<br /> let visited' = clearBit visited square<br /> in if visited' == 0<br /> then return (reverse $ map toSquare (square : list))<br /> else do m <- findMoves square visited<br /> solutionsF m visited' (square : list)<br />B.Listing the moves <br />This only leaves the challenge of writing findMoves :: Bits a => Int -> a -> [Int]. This is where things get a little tricky... at first glance it seems we need to convert an integer, to a board square, to a list of board squares (nextMoves) to a list of integers, and finally to a filtered list of integers. This all seems rather wasteful. <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:findMovesquot;
findMoves>>=<br />findMoves :: Bits a => Int -> a -> [Int]<br />findMoves sqr visited = <br /> movesList sqr $ filteredMoves sqr visited<br />filteredMoves :: Bits a => Int -> a -> b then finds the available moves and movesList :: Int -> b -> [Int] converts this to a list. The next question is then: what is a suitable type to easily represent a list of moves from a 64-bit word? The answer: a 64-bit word! <br />More precisely: a 64-bit word centered around the 'reference square', (3,3). We can then write filteredMoves as follows: <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:filteredMovesquot;
filteredMoves>>=<br />filteredMoves :: Bits a => Int -> a -> a<br />filteredMoves sqr visited = <br /> let x = sqr `mod` 8<br /> mask<br /> | x == 0 = makeMask (3 <=)<br /> | x == 1 = makeMask (2 <=)<br /> | x == 7 = makeMask (3 >=)<br /> | x == 6 = makeMask (4 >=)<br /> | otherwise = makeMask (const True)<br /> in mask .&. shiftR visited (sqr - fromSquare (3,3))<br />The last line is the most interesting: it shows that we can perform the filter operation as two bitwise operations. <br />The remainder of this function concentrates on ensuring that the mask does not include values 'off the edge of the board'. It does this by filtering the mask (the list of moves) when the x coordinate approaches the edge. <br />makeMask is given as follows: <br /><< HYPERLINK quot;
http://en.literateprograms.org/The_Knight%27s_Tour_%28Haskell%29quot;
quot;
chunk%20use:makeMaskquot;
makeMask>>=<br />makeMask::Bits a => (Int -> Bool) -> a<br />makeMask f = <br /> foldl setBit 0 $ map fromSquare $ filter (f . fst) (nextMoves (3,3))<br />C.Performing the Knight's Tour <br />To perform the Knight's Tour, you only need a pencil and paper. Draw an 8x8 grid, and fill in the coordinates (algebraic and linear). You can also carry around a portable chess board, with each square marked. Remember that you'll also need some way to mark squares that have already been landed upon. <br />To begin the performance, you may need to explain the nature of the challenge first. Introduce the board, and explain how the knight moves, and that you have to hit each square. You can also offer to look away or be blindfolded during the challenge. <br />To start the challenge itself, have your spectator choose a starting square. <br />From this point, simply recall your links, and have the audience member cross out the squares as you call them, until you get to the final square. Don't forget the square on which you started, so you don't overshoot the final square. <br />D.Memorizing the Path <br />To memorize the path, you'll simply link each coordinate to the following coordinate in the path list. <br />With the linear coordinates, you might link TIE (1) to DOVE (18), then DOVE (18) to MULE (35), and so on, finishing with linking TOT (11) to TIE (1). <br />With the algebraic coordinates, you might link A VOW (a8) to BEACH (b6), then BEACH (b6) to CAR (c4), and so on, finishing with linking CAKE (c7) to A VOW (a8). <br />