|         |      1 // Preliminary Part about finding Knight's tours | 
|         |      2 //=============================================== | 
|         |      3  | 
|         |      4  | 
|         |      5 object CW9a { | 
|         |      6  | 
|         |      7 // If you need any auxiliary function, feel free to  | 
|         |      8 // implement it, but do not make any changes to the | 
|         |      9 // templates below. Also have a look whether the functions | 
|         |     10 // at the end are of any help. | 
|         |     11  | 
|         |     12  | 
|         |     13  | 
|         |     14 type Pos = (Int, Int)    // a position on a chessboard  | 
|         |     15 type Path = List[Pos]    // a path...a list of positions | 
|         |     16  | 
|         |     17 //(1) Complete the function that tests whether the position x | 
|         |     18 //    is inside the board and not yet element in the path. | 
|         |     19  | 
|         |     20 def is_legal(dim: Int, path: Path, x: Pos) : Boolean = {  | 
|         |     21   if ((!(path.contains(x))) && (x._1 >= 0) && (x._2 >= 0) && (x._1 < dim) && (x._2 < dim)) | 
|         |     22     true | 
|         |     23   else false | 
|         |     24 } | 
|         |     25  | 
|         |     26 //(2) Complete the function that calculates for a position x | 
|         |     27 //    all legal onward moves that are not already in the path.  | 
|         |     28 //    The moves should be ordered in a "clockwise" manner. | 
|         |     29   | 
|         |     30  | 
|         |     31 def legal_moves(dim: Int, path: Path, x: Pos) : List[Pos] = {//List[Pos] | 
|         |     32   val changes = List((1,2),(2,1),(2,-1),(1,-2),(-1,-2),(-2,-1),(-2,1),(-1,2)) | 
|         |     33   val returnList = (for ((y,z) <- changes) yield( | 
|         |     34     //println(y,z)-2,-1 | 
|         |     35     if ((is_legal(dim,path,((x._1 + y) , (x._2 + z)))) == true) | 
|         |     36       Some(x._1 + y , x._2 + z) | 
|         |     37     else | 
|         |     38       None | 
|         |     39   )) | 
|         |     40   returnList.flatten | 
|         |     41 } | 
|         |     42  | 
|         |     43  | 
|         |     44 //some testcases | 
|         |     45 // | 
|         |     46 //assert(legal_moves(8, Nil, (2,2)) ==  | 
|         |     47   //List((3,4), (4,3), (4,1), (3,0), (1,0), (0,1), (0,3), (1,4))) | 
|         |     48 //assert(legal_moves(8, Nil, (7,7)) == List((6,5), (5,6))) | 
|         |     49 //assert(legal_moves(8, List((4,1), (1,0)), (2,2)) ==  | 
|         |     50 //  List((3,4), (4,3), (3,0), (0,1), (0,3), (1,4))) | 
|         |     51 //assert(legal_moves(8, List((6,6)), (7,7)) == List((6,5), (5,6))) | 
|         |     52  | 
|         |     53  | 
|         |     54 //(3) Complete the two recursive functions below.  | 
|         |     55 //    They exhaustively search for knight's tours starting from the  | 
|         |     56 //    given path. The first function counts all possible tours,  | 
|         |     57 //    and the second collects all tours in a list of paths. | 
|         |     58  | 
|         |     59 def count_tours(dim: Int, path: Path) : Int = (dim,path) match {//Int | 
|         |     60   case (_, Nil) => 0 | 
|         |     61   case (0, path) => 0 | 
|         |     62   case (dim, path) => { if (legal_moves(dim,path, path.head).size == 0)  | 
|         |     63 				if(path.size < dim*dim)  | 
|         |     64 					0  | 
|         |     65 				else  | 
|         |     66 					1 | 
|         |     67 			else (for (j <- legal_moves(dim,path, path.head)) yield count_tours(dim,j::path)).sum | 
|         |     68 			} | 
|         |     69 } | 
|         |     70  | 
|         |     71 def enum_tours(dim: Int, path: Path) : List[Path] = (dim,path) match { | 
|         |     72   case (_, Nil) => Nil | 
|         |     73   case (0, path) => Nil | 
|         |     74   case (dim, path) =>	{ if (legal_moves(dim,path, path.head).size == 0)  | 
|         |     75 				if(path.size < dim*dim)  | 
|         |     76 					Nil | 
|         |     77 				else  | 
|         |     78 					List(path) | 
|         |     79 			else (for (j <- legal_moves(dim,path, path.head)) yield enum_tours(dim,j::path)).flatten | 
|         |     80 			} | 
|         |     81 			 | 
|         |     82 } | 
|         |     83  | 
|         |     84  | 
|         |     85 //(4) Implement a first-function that finds the first  | 
|         |     86 //    element, say x, in the list xs where f is not None.  | 
|         |     87 //    In that case Return f(x), otherwise None. If possible, | 
|         |     88 //    calculate f(x) only once. | 
|         |     89  | 
|         |     90 //def first(xs: List[Pos], f: Pos => Option[Path]) : Option[Path] = ... | 
|         |     91  | 
|         |     92  | 
|         |     93 // testcases | 
|         |     94 // | 
|         |     95 //def foo(x: (Int, Int)) = if (x._1 > 3) Some(List(x)) else None | 
|         |     96 // | 
|         |     97 //first(List((1, 0),(2, 0),(3, 0),(4, 0)), foo)   // Some(List((4,0))) | 
|         |     98 //first(List((1, 0),(2, 0),(3, 0)), foo)          // None | 
|         |     99  | 
|         |    100  | 
|         |    101 //(5) Implement a function that uses the first-function from (5) for | 
|         |    102 //    trying out onward moves, and searches recursively for a | 
|         |    103 //    knight tour on a dim * dim-board. | 
|         |    104  | 
|         |    105  | 
|         |    106 //def first_tour(dim: Int, path: Path) : Option[Path] = ... | 
|         |    107   | 
|         |    108  | 
|         |    109  | 
|         |    110  | 
|         |    111  | 
|         |    112  | 
|         |    113 /* Helper functions | 
|         |    114  | 
|         |    115  | 
|         |    116 // for measuring time | 
|         |    117 def time_needed[T](code: => T) : T = { | 
|         |    118   val start = System.nanoTime() | 
|         |    119   val result = code | 
|         |    120   val end = System.nanoTime() | 
|         |    121   println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.") | 
|         |    122   result | 
|         |    123 } | 
|         |    124  | 
|         |    125 // can be called for example with | 
|         |    126 //     time_needed(count_tours(dim, List((0, 0)))) | 
|         |    127 // in order to print out the time that is needed for  | 
|         |    128 // running count_tours | 
|         |    129  | 
|         |    130  | 
|         |    131  | 
|         |    132  | 
|         |    133 // for printing a board | 
|         |    134 def print_board(dim: Int, path: Path): Unit = { | 
|         |    135   println | 
|         |    136   for (i <- 0 until dim) { | 
|         |    137     for (j <- 0 until dim) { | 
|         |    138       print(f"${path.reverse.indexOf((j, dim - i - 1))}%3.0f ") | 
|         |    139     } | 
|         |    140     println | 
|         |    141   }  | 
|         |    142 } | 
|         |    143  | 
|         |    144  | 
|         |    145 */ | 
|         |    146  | 
|         |    147 } |