| 163 |      1 | 
 | 
| 145 |      2 | // Part 1 about finding and counting Knight's tours
 | 
|  |      3 | //==================================================
 | 
|  |      4 | 
 | 
| 163 |      5 | object CW7a extends App{
 | 
| 145 |      6 | 
 | 
|  |      7 | type Pos = (Int, Int)    // a position on a chessboard 
 | 
|  |      8 | type Path = List[Pos]    // a path...a list of positions
 | 
|  |      9 | 
 | 
| 163 |     10 | //(1a) Complete the function that tests whether the position 
 | 
|  |     11 | //     is inside the board and not yet element in the path.
 | 
|  |     12 | 
 | 
|  |     13 | //def is_legal(dim: Int, path: Path)(x: Pos) : Boolean = ...
 | 
| 145 |     14 | 
 | 
| 163 |     15 | def is_legal(dim: Int, path: Path)(x: Pos) : Boolean = {
 | 
|  |     16 |   
 | 
|  |     17 | // if ((x._1<dim && x._2<dim) && (x._1>0 || x._2>0)) false else !path.contains(x)
 | 
|  |     18 |  
 | 
|  |     19 |   if (x._1 < 0 || x._2 < 0) false 
 | 
|  |     20 |   else if (x._1 < dim && x._2 < dim && !path.contains(x)) true 
 | 
|  |     21 |   else false
 | 
|  |     22 |  
 | 
|  |     23 |   
 | 
|  |     24 | }
 | 
| 145 |     25 | 
 | 
|  |     26 | 
 | 
|  |     27 | 
 | 
| 163 |     28 | def legal_moves(dim: Int, path: Path, x: Pos) : List[Pos] = {
 | 
|  |     29 |   
 | 
|  |     30 |   val allPossibleMoves = List((x._1+1, x._2+2), (x._1+2, x._2+1), (x._1+2, x._2-1), (x._1+1, x._2-2), (x._1-1, x._2-2), (x._1-2, x._2-1), (x._1-2, x._2+1), (x._1-1, x._2+2));
 | 
|  |     31 |  
 | 
|  |     32 |   //val finalList = allPossibleMoves.filter((a=>a._1<dim && a._2<dim && x._1 >= 0 && a._2 >= 0));
 | 
| 154 |     33 |   
 | 
| 163 |     34 |   val finalList = for(pos<-allPossibleMoves if(is_legal(dim,path)(pos))) yield pos;
 | 
|  |     35 |   
 | 
|  |     36 |   // println("Space in board: " + dim*dim + " for dim: " + dim)
 | 
|  |     37 |    
 | 
|  |     38 |   
 | 
|  |     39 |   finalList.toList;
 | 
| 154 |     40 |     
 | 
|  |     41 |   
 | 
|  |     42 | }
 | 
|  |     43 | 
 | 
| 163 |     44 | println(legal_moves(8, Nil, (2,2)))
 | 
|  |     45 | println(legal_moves(8, Nil, (7,7)))
 | 
|  |     46 | println(legal_moves(8, List((4,1), (1,0)), (2,2)))
 | 
|  |     47 | println(legal_moves(8, List((6,6)), (7,7)))
 | 
|  |     48 | println(legal_moves(1, Nil, (0,0)))
 | 
|  |     49 | println(legal_moves(2, Nil, (0,0)))
 | 
|  |     50 | println(legal_moves(3, Nil, (0,0)))
 | 
|  |     51 | 
 | 
|  |     52 | println("=================================================================================")
 | 
|  |     53 | println("================================Comparision output===============================")
 | 
|  |     54 | println("=================================================================================")
 | 
|  |     55 | 
 | 
|  |     56 | println(legal_moves(8, Nil, (2,2)) == List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4)))
 | 
|  |     57 | println(legal_moves(8, Nil, (7,7)) == List((6,5), (5,6)))
 | 
|  |     58 | println(legal_moves(8, List((4,1), (1,0)), (2,2)) == List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4)))
 | 
|  |     59 | println(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6)))
 | 
|  |     60 | println(legal_moves(1, Nil, (0,0)) == Nil)
 | 
|  |     61 | println(legal_moves(2, Nil, (0,0)) == Nil)
 | 
|  |     62 | println(legal_moves(3, Nil, (0,0)) == List((1,2), (2,1)))
 | 
|  |     63 | 
 | 
| 145 |     64 | 
 | 
| 163 |     65 | def count_tours(dim: Int, path: Path) : Int = {
 | 
|  |     66 |      
 | 
|  |     67 |   val allMovesFromCurrentPosition = legal_moves(dim, path, path.head);
 | 
|  |     68 |   
 | 
|  |     69 |   if (path.length == dim*dim) 1 else  {
 | 
|  |     70 |     
 | 
|  |     71 |     if (allMovesFromCurrentPosition.size == 0 ) 0  else {
 | 
|  |     72 |       
 | 
|  |     73 |       allMovesFromCurrentPosition.map( element => count_tours(dim, element::path)).sum
 | 
|  |     74 |       
 | 
|  |     75 |       
 | 
|  |     76 |     }
 | 
|  |     77 |     
 | 
|  |     78 |   }
 | 
|  |     79 |   
 | 
| 145 |     80 | }
 | 
| 163 |     81 |     
 | 
|  |     82 |   
 | 
| 145 |     83 | 
 | 
| 163 |     84 | println ( count_tours(5, List((0,0))) )
 | 
|  |     85 | 
 | 
|  |     86 | def enum_tours(dim: Int, path: Path) : List[Path] = {
 | 
|  |     87 |   
 | 
|  |     88 |      val allMovesFromCurrentPosition = legal_moves(dim, path, path.head);
 | 
|  |     89 |   
 | 
|  |     90 |   if (path.length == dim*dim) List(path) else  {
 | 
|  |     91 |     
 | 
|  |     92 |   allMovesFromCurrentPosition.map( element => enum_tours(dim, element::path)).flatten ;
 | 
|  |     93 |       
 | 
|  |     94 |       
 | 
|  |     95 |       }
 | 
|  |     96 |     }
 | 
|  |     97 |   println ( enum_tours(6, List((0,2))).size)
 | 
| 145 |     98 | }
 | 
|  |     99 | 
 | 
| 163 |    100 | 
 | 
|  |    101 | 
 | 
|  |    102 | 
 | 
| 145 |    103 | 
 | 
| 163 |    104 |  
 | 
|  |    105 |  
 | 
|  |    106 | //(1b) Complete the function that calculates for a position 
 | 
|  |    107 | //     all legal onward moves that are not already in the path. 
 | 
|  |    108 | //     The moves should be ordered in a "clockwise" manner.
 | 
|  |    109 |  
 | 
|  |    110 | //def legal_moves(dim: Int, path: Path, x: Pos) : List[Pos] = ...
 | 
|  |    111 | 
 | 
|  |    112 | 
 | 
|  |    113 | 
 | 
| 145 |    114 | 
 | 
| 163 |    115 | //some test cases
 | 
|  |    116 | //
 | 
|  |    117 | //assert(legal_moves(8, Nil, (2,2)) == 
 | 
|  |    118 | //  List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4)))
 | 
|  |    119 | //assert(legal_moves(8, Nil, (7,7)) == List((6,5), (5,6)))
 | 
|  |    120 | //assert(legal_moves(8, List((4,1), (1,0)), (2,2)) == 
 | 
|  |    121 | //  List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4)))
 | 
|  |    122 | //assert(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6)))
 | 
|  |    123 | 
 | 
| 145 |    124 | 
 | 
| 163 |    125 | //(1c) Complete the two recursive functions below. 
 | 
|  |    126 | //     They exhaustively search for knight's tours starting from the 
 | 
|  |    127 | //     given path. The first function counts all possible tours, 
 | 
|  |    128 | //     and the second collects all tours in a list of paths.
 | 
|  |    129 | 
 | 
|  |    130 | //def count_tours(dim: Int, path: Path) : Int = ...
 | 
|  |    131 | 
 | 
|  |    132 | 
 | 
|  |    133 | //def enum_tours(dim: Int, path: Path) : List[Path] = ...
 |