| author | Christian Urban <christian.urban@kcl.ac.uk> | 
| Sat, 29 Aug 2020 16:05:59 +0100 | |
| changeset 342 | 3779dd003077 | 
| parent 213 | 5a5acaf4b32b | 
| permissions | -rw-r--r-- | 
| 50 | 1 | // Part 2 about finding a single tour for a board | 
| 2 | //================================================ | |
| 4 | 3 | |
| 50 | 4 | type Pos = (Int, Int) // a position on a chessboard | 
| 5 | type Path = List[Pos] // a path...a list of positions | |
| 4 | 6 | |
| 42 
a5106bc13db6
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
39diff
changeset | 7 | |
| 213 | 8 | // for measuring time | 
| 9 | def time_needed[T](n: Int, code: => T) : T = {
 | |
| 10 | val start = System.nanoTime() | |
| 11 | for (i <- 0 until n) code | |
| 12 | val result = code | |
| 13 | val end = System.nanoTime() | |
| 14 |   println("Time needed: " + (end - start) / 1.0e9 + " secs.")
 | |
| 15 | result | |
| 16 | } | |
| 17 | ||
| 42 
a5106bc13db6
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
39diff
changeset | 18 | |
| 213 | 19 | def print_board(dim: Int, path: Path): Unit = {
 | 
| 20 | println | |
| 21 |   for (i <- 0 until dim) {
 | |
| 22 |     for (j <- 0 until dim) {
 | |
| 23 |       print(f"${path.reverse.indexOf((i, j))}%3.0f ")
 | |
| 24 | } | |
| 25 | println | |
| 26 | } | |
| 27 | } | |
| 28 | ||
| 29 | def add_pair(x: Pos)(y: Pos): Pos = | |
| 30 | (x._1 + y._1, x._2 + y._2) | |
| 31 | ||
| 32 | def is_legal(dim: Int, path: Path)(x: Pos): Boolean = | |
| 33 | 0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x) | |
| 34 | ||
| 35 | def moves(x: Pos): List[Pos] = | |
| 36 | List(( 1, 2),( 2, 1),( 2, -1),( 1, -2), | |
| 37 | (-1, -2),(-2, -1),(-2, 1),(-1, 2)).map(add_pair(x)) | |
| 38 | ||
| 39 | def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = | |
| 40 | moves(x).filter(is_legal(dim, path)) | |
| 41 | ||
| 44 
9cfa37c91444
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
43diff
changeset | 42 | |
| 213 | 43 | def first(xs: List[Pos], f: Pos => Option[Path]): Option[Path] = xs match {
 | 
| 44 | case Nil => None | |
| 45 |   case x::xs => {
 | |
| 46 | val result = f(x) | |
| 47 | if (result.isDefined) result else first(xs, f) | |
| 48 | } | |
| 49 | } | |
| 50 | ||
| 51 | first(List((1, 0),(2, 0),(3, 0),(4, 0)), (x => if (x._1 > 3) Some(List(x)) else None)) | |
| 52 | first(List((1, 0),(2, 0),(3, 0)), (x => if (x._1 > 3) Some(List(x)) else None)) | |
| 53 | ||
| 54 | ||
| 55 | ||
| 56 | def first_tour(dim: Int, path: Path): Option[Path] = {
 | |
| 57 | if (path.length == dim * dim) Some(path) | |
| 58 | else | |
| 59 | first(legal_moves(dim, path, path.head), (x: Pos) => first_tour(dim, x::path)) | |
| 60 | } | |
| 44 
9cfa37c91444
updated
 Christian Urban <christian dot urban at kcl dot ac dot uk> parents: 
43diff
changeset | 61 | |
| 213 | 62 | /* | 
| 63 | for (dim <- 1 to 8) {
 | |
| 64 | val t = first_tour(dim, List((0, 0))) | |
| 65 |   println(s"${dim} x ${dim} " + (if (t == None) "" else { print_board(dim, t.get) ; "" }))
 | |
| 66 | } | |
| 67 | */ | |
| 68 | ||
| 69 | // 15 secs for 8 x 8 | |
| 70 | val ts1 = time_needed(0,first_tour(8, List((0, 0))).get) | |
| 71 | ||
| 72 | // no result for 4 x 4 | |
| 73 | val ts2 = time_needed(0, first_tour(4, List((0, 0)))) | |
| 74 | ||
| 75 | // 0.3 secs for 6 x 6 | |
| 76 | val ts3 = time_needed(0, first_tour(6, List((0, 0)))) | |
| 77 | ||
| 78 | // 15 secs for 8 x 8 | |
| 79 | time_needed(0, print_board(8, first_tour(8, List((0, 0))).get)) | |
| 80 | ||
| 81 |