main_solution4/knight3.scala
changeset 477 a4e1f63157d8
parent 476 7550c816187a
child 478 191cd1de93f1
equal deleted inserted replaced
476:7550c816187a 477:a4e1f63157d8
     1 // Part 3 about finding a single tour using the Warnsdorf Rule
       
     2 //=============================================================
       
     3 
       
     4 object M4c { // for preparing the jar
       
     5 
       
     6 type Pos = (Int, Int)
       
     7 type Path = List[Pos]
       
     8 
       
     9 
       
    10 // for measuring time in the JAR
       
    11 def time_needed[T](code: => T) : T = {
       
    12   val start = System.nanoTime()
       
    13   val result = code
       
    14   val end = System.nanoTime()
       
    15   println(f"Time needed: ${(end - start) / 1.0e9}%3.3f secs.")
       
    16   result
       
    17 }
       
    18 
       
    19 
       
    20 def print_board(dim: Int, path: Path): Unit = {
       
    21   println()
       
    22   for (i <- 0 until dim) {
       
    23     for (j <- 0 until dim) {
       
    24       print(f"${path.reverse.indexOf((i, j))}%4.0f ")
       
    25     }
       
    26     println()
       
    27   } 
       
    28 }
       
    29 
       
    30 def add_pair(x: Pos, y: Pos): Pos = 
       
    31   (x._1 + y._1, x._2 + y._2)
       
    32 
       
    33 def is_legal(dim: Int, path: Path, x: Pos): Boolean = 
       
    34   0 <= x._1 && 0 <= x._2 && x._1 < dim && x._2 < dim && !path.contains(x)
       
    35 
       
    36 def moves(x: Pos): List[Pos] = 
       
    37   List(( 1,  2),( 2,  1),( 2, -1),( 1, -2),
       
    38        (-1, -2),(-2, -1),(-2,  1),(-1,  2)).map(add_pair(x, _))
       
    39 
       
    40 def legal_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
       
    41   moves(x).filter(is_legal(dim, path, _))
       
    42  
       
    43 def ordered_moves(dim: Int, path: Path, x: Pos): List[Pos] = 
       
    44   legal_moves(dim, path, x).sortBy((x) => legal_moves(dim, path, x).length)
       
    45 
       
    46 import scala.annotation.tailrec
       
    47 
       
    48 @tailrec
       
    49 def tour_on_mega_board_aux(dim: Int, paths: List[Path]): Option[Path] = paths match {
       
    50   case Nil => None
       
    51   case (path::rest) =>
       
    52     if (path.length == dim * dim) Some(path)
       
    53     else tour_on_mega_board_aux(dim, ordered_moves(dim, path, path.head).map(_::path) ::: rest)
       
    54 }
       
    55 
       
    56 def ttour_on_mega_board(dim: Int, path: Path): Option[Path] =
       
    57   tour_on_mega_board_aux(dim, List(path))
       
    58 
       
    59 
       
    60 def tour_on_mega_board(dim: Int, path: Path) =
       
    61   time_needed(ttour_on_mega_board(dim: Int, path: Path))
       
    62 
       
    63 
       
    64 // testcases
       
    65 //print_board(70, tour_on_mega_board(70, List((0, 0))).get)
       
    66 
       
    67 
       
    68 }
       
    69 
       
    70 
       
    71 //val dim = 66 //75
       
    72 M4c.print_board(30, M4c.tour_on_mega_board(30, List((0, 0))).get)
       
    73 M4c.print_board(66, M4c.tour_on_mega_board(66, List((0, 0))).get)