progs/cube.scala
changeset 417 29fc780ca130
child 463 0315d9983cd0
equal deleted inserted replaced
416:497f67fd4ae0 417:29fc780ca130
       
     1 // 2 x 2 x 2 Rubik's Cube
       
     2 //========================
       
     3 
       
     4 // more memory for the JVM
       
     5 //
       
     6 // JAVA_OPTS="-Xmx2g" scala
       
     7 
       
     8 
       
     9 // for measuring memory usage
       
    10 val mb = 1024*1024
       
    11 val runtime = Runtime.getRuntime
       
    12 
       
    13 def memory() = {
       
    14   println(s"  ** Used Memory:  ${(runtime.totalMemory - runtime.freeMemory) / mb}")
       
    15   println(s"  ** Free Memory:  ${runtime.freeMemory / mb}")
       
    16   println(s"  ** Total Memory: ${runtime.totalMemory / mb}")
       
    17   println(s"  ** Max Memory:   ${runtime.maxMemory / mb}")
       
    18 }
       
    19 
       
    20 
       
    21 abstract class Colour
       
    22 case object White extends Colour
       
    23 case object Yellow extends Colour
       
    24 case object Orange extends Colour
       
    25 case object Red extends Colour
       
    26 case object Green extends Colour
       
    27 case object Blue extends Colour
       
    28 
       
    29 // Faces
       
    30 //    -------
       
    31 //   |c11 c12|
       
    32 //   |c21 c22|
       
    33 //    -------  
       
    34 case class Face(c11: Colour, c12: Colour,
       
    35                 c21: Colour, c22: Colour)
       
    36 
       
    37 
       
    38 // Cubes
       
    39 //     +--+
       
    40 //     |f2|
       
    41 //  +--+  +--+
       
    42 //  |f5 f1 f6|
       
    43 //  +--+  +--+
       
    44 //     |f3|
       
    45 //     |f4|
       
    46 //     +--+ 
       
    47 case class Cube(f1: Face, f2: Face, f3: Face,
       
    48                 f4: Face, f5: Face, f6: Face)
       
    49 
       
    50 
       
    51 // starting cube
       
    52 val init = 
       
    53     Cube(Face(White, Green, White, White), 
       
    54          Face(Blue, Yellow, Orange, Red), 
       
    55          Face(Red, Blue, Red, Blue),
       
    56          Face(White, Yellow, Red, Orange),
       
    57          Face(Yellow, Green, Blue, Green),
       
    58          Face(Yellow, Green, Orange, Orange))
       
    59 
       
    60 // solved cube
       
    61 val solved = 
       
    62     Cube(Face(Yellow, Yellow, Yellow, Yellow), 
       
    63          Face(Orange, Orange, Orange, Orange), 
       
    64          Face(Red, Red, Red, Red),
       
    65          Face(White, White, White, White),
       
    66          Face(Blue, Blue, Blue, Blue),
       
    67          Face(Green, Green, Green, Green))  
       
    68 
       
    69 
       
    70 
       
    71 // actions
       
    72 def up(c: Cube) : Cube =
       
    73     Cube(Face(c.f1.c11, c.f3.c12, c.f1.c21, c.f3.c22),
       
    74          Face(c.f2.c11, c.f1.c12, c.f2.c21, c.f1.c22),
       
    75          Face(c.f3.c11, c.f4.c12, c.f3.c21, c.f4.c22),
       
    76          Face(c.f4.c11, c.f2.c12, c.f4.c21, c.f2.c22),
       
    77          Face(c.f5.c11, c.f5.c12, c.f5.c21, c.f5.c22),
       
    78          Face(c.f6.c21, c.f6.c11, c.f6.c22, c.f6.c12))
       
    79 
       
    80 def clock(c: Cube) : Cube =
       
    81     Cube(Face(c.f1.c21, c.f1.c11, c.f1.c22, c.f1.c12),
       
    82          Face(c.f2.c11, c.f2.c12, c.f5.c22, c.f5.c12),
       
    83          Face(c.f6.c21, c.f6.c11, c.f3.c21, c.f3.c22),
       
    84          Face(c.f4.c11, c.f4.c12, c.f4.c21, c.f4.c22),
       
    85          Face(c.f5.c11, c.f3.c11, c.f5.c21, c.f3.c12),
       
    86          Face(c.f2.c21, c.f6.c12, c.f2.c22, c.f6.c22))
       
    87 
       
    88 def right(c: Cube) : Cube =
       
    89     Cube(Face(c.f5.c11, c.f5.c12, c.f1.c21, c.f1.c22),
       
    90          Face(c.f2.c12, c.f2.c22, c.f2.c11, c.f2.c21),
       
    91          Face(c.f3.c11, c.f3.c12, c.f3.c21, c.f3.c22),
       
    92          Face(c.f4.c11, c.f4.c12, c.f6.c12, c.f6.c11),
       
    93          Face(c.f4.c22, c.f4.c21, c.f5.c21, c.f5.c22),
       
    94          Face(c.f1.c11, c.f1.c12, c.f6.c21, c.f6.c22))         
       
    95 
       
    96 
       
    97 // simple bf-search without solution, just true
       
    98 
       
    99 def actions(c: Cube) : List[Cube] = 
       
   100   List(up(c), clock(c), right(c)) 
       
   101 
       
   102 def search(cs: List[Cube], d: Int) : Boolean = { 
       
   103   println(s"Depth: $d    Cands: ${cs.length}")  
       
   104   //memory()
       
   105   if (cs.exists(solved == _)) true
       
   106   else search(cs.flatMap(actions), d + 1)
       
   107 }  
       
   108 
       
   109 search(List(init), 0)
       
   110 
       
   111 // Set version
       
   112 def actions_set(c: Cube) : Set[Cube] =
       
   113   Set(up(c), clock(c), right(c))
       
   114 
       
   115 def search_set(cs: Set[Cube], d: Int) : Boolean = {
       
   116   println(s"Depth: $d candidates: ${cs.size}")
       
   117   //memory()
       
   118   if (cs.contains(solved)) true
       
   119   else search_set(cs.flatMap(actions_set), d + 1)
       
   120 }  
       
   121 
       
   122 search_set(Set(init), 0)
       
   123 
       
   124 
       
   125 // For generating list of actions
       
   126 abstract class Action
       
   127 case object Up extends Action
       
   128 case object Right extends Action
       
   129 case object Clock extends Action
       
   130 
       
   131 type Actions = List[Action]
       
   132 
       
   133 // List version generating a list of actions
       
   134 def actions_list(c: Cube, act: Actions) : List[(Cube, Actions)] = 
       
   135   List((up(c), Up::act), 
       
   136        (clock(c), Clock::act), 
       
   137        (right(c), Right::act)) 
       
   138 
       
   139 
       
   140 def search_list(cs: List[(Cube, Actions)], d: Int) : (Cube, Actions) = { 
       
   141   println(s"Depth: $d    Cands: ${cs.length}")  
       
   142   val res = cs.find(_._1 == solved)
       
   143   if (res.isDefined) res.get
       
   144   else search_list(cs.flatMap{case (c, as) => actions_list(c, as) }, d + 1)
       
   145 }  
       
   146 
       
   147 search_list(List((init, Nil)), 0)._2.reverse.mkString("\n") 
       
   148 
       
   149 
       
   150 // Map version generating a list of actions
       
   151 def actions_map(c: Cube, as: Actions) : Map[Cube, Actions] = 
       
   152   Map(up(c) -> (Up::as), 
       
   153       clock(c) -> (Clock::as), 
       
   154       right(c) -> (Right::as)) 
       
   155 
       
   156 
       
   157 def search_map(cs: Map[Cube, Actions], d: Int) : Actions = { 
       
   158   println(s"Depth: $d    Cands: ${cs.keySet.size}")  
       
   159   val res = cs.keySet.find(_ == solved)
       
   160   if (res.isDefined) cs(res.get)
       
   161   else search_map(cs.flatMap{case (c, as) => actions_list(c, as) }, d + 1)
       
   162 }  
       
   163 
       
   164 
       
   165 search_map(Map(init -> Nil), 0).reverse.mkString("\n")
       
   166 
       
   167 
       
   168 
       
   169 // Bidirectional breadth-first search
       
   170 def bsearch(cs: Map[Cube, Actions], 
       
   171             bs: Map[Cube, Actions], d: Int) : Actions = { 
       
   172   println(s"Depth: $d    Cands: ${cs.keySet.size}/${bs.keySet.size}") 
       
   173   val res = cs.keySet intersect bs.keySet 
       
   174   if (!res.isEmpty) (cs(res.head).reverse ::: bs(res.head))
       
   175   else bsearch(cs.flatMap{case (c, as) => actions_map(c, as) }, 
       
   176                bs.flatMap{case (c, as) => actions_map(c, as) }, d + 1)
       
   177 }  
       
   178 
       
   179 bsearch(Map(init ->  Nil), Map(solved -> Nil), 0).mkString("\n")
       
   180 
       
   181 
       
   182 
       
   183 
       
   184 
       
   185 
       
   186 
       
   187 
       
   188 
       
   189 
       
   190 
       
   191 
       
   192 
       
   193 
       
   194 
       
   195 
       
   196 
       
   197 
       
   198 
       
   199