/Rubik2.py

https://github.com/chetmancini/Rubik-s-Cube
Python | 415 lines | 317 code | 35 blank | 63 comment | 16 complexity | d6da6691459dd13fa59f5de6e7392620 MD5 | raw file
  1. # Author Chet Mancini
  2. # Disclaimer - this code needs a lot of work.
  3. # There's a lot that can be refactored at the moment!
  4. # I just had to get it working for class.
  5. import sys, copy
  6. # Easy hack for enums. Not terribly pythonic, but will get job done here.
  7. class Color:
  8. B = "B"
  9. W = "W"
  10. Y = "Y"
  11. R = "R"
  12. G = "G"
  13. O = "O"
  14. class Face:
  15. face = []
  16. def rotateClock(self):
  17. temp = self.face
  18. temp[0] = self.face[6]
  19. temp[1] = self.face[3]
  20. temp[2] = self.face[0]
  21. temp[3] = self.face[7]
  22. #faceClone[4] = face[4] (always static)
  23. temp[5] = self.face[1]
  24. temp[6] = self.face[8]
  25. temp[7] = self.face[5]
  26. temp[8] = self.face[2]
  27. self.face = temp
  28. def rotateCounter(self):
  29. temp = self.face
  30. temp[0] = self.face[2]
  31. temp[1] = self.face[5]
  32. temp[2] = self.face[8]
  33. temp[3] = self.face[1]
  34. #faceClone[4] = face[4] (always static)
  35. temp[5] = self.face[7]
  36. temp[6] = self.face[0]
  37. temp[7] = self.face[3]
  38. temp[8] = self.face[6]
  39. self.face = temp
  40. def allSameColor():
  41. color = face[0]
  42. for test in face:
  43. if test != color:
  44. return False
  45. return True
  46. class Rubik:
  47. paths = []
  48. top = Face()
  49. bottom = Face()
  50. left = Face()
  51. right = Face()
  52. front = Face()
  53. back = Face()
  54. # Representation is stored in a 9-element list
  55. # 1-3, 4-6, 7-9
  56. def __init__(self):
  57. paths = []
  58. def successors(self):
  59. toReturn = []
  60. TopCounter = copy.deepcopy(self)
  61. topCounter(TopCounter)
  62. TopCounter.paths.append("TCo")
  63. toReturn.append(TopCounter)
  64. TopClock = copy.deepcopy(self)
  65. topClock(TopClock)
  66. TopClock.paths.append("TCl")
  67. toReturn.append(TopClock)
  68. # LeftForward = copy.deepcopy(self)
  69. # LeftForward.leftForward()
  70. # LeftForward.paths.append("LF")
  71. # toReturn.append(LeftForward)
  72. #
  73. # LeftBackward = copy.deepcopy(self)
  74. # LeftBackward.leftBackward()
  75. # LeftBackward.paths.append("LB")
  76. # toReturn.append(LeftBackward)
  77. #
  78. # RightForward = copy.deepcopy(self)
  79. # RightForward.rightForward()
  80. # RightForward.paths.append("RF")
  81. # toReturn.append(RightForward)
  82. #
  83. # RightBackward = copy.deepcopy(self)
  84. # RightBackward.rightBackward()
  85. # RightBackward.paths.append("RB")
  86. # toReturn.append(RightBackward)
  87. #
  88. # BottomCounter = copy.deepcopy(self)
  89. # BottomCounter.bottomCounter()
  90. # BottomCounter.paths.append("BCo")
  91. # toReturn.append(BottomCounter)
  92. #
  93. # BottomClock = copy.deepcopy(self)
  94. # BottomClock.bottomClock()
  95. # BottomClock.paths.append("BCl")
  96. # toReturn.append(BottomClock)
  97. #
  98. # FrontClock = copy.deepcopy(self)
  99. # FrontClock.frontClock()
  100. # FrontClock.paths.append("FCl")
  101. # toReturn.append(FrontClock)
  102. #
  103. # FrontCounter = copy.deepcopy(self)
  104. # FrontCounter.frontCounter()
  105. # FrontCounter.paths.append("FCo")
  106. # toReturn.append(FrontCounter)
  107. # print FrontCounter.dictKey()
  108. #
  109. # BackClock = copy.deepcopy(self)
  110. # BackClock.backClock()
  111. # BackClock.paths.append("BaCl")
  112. # toReturn.append(BackClock)
  113. # print BackClock.dictKey()
  114. #
  115. # BackCounter = copy.deepcopy(self)
  116. # BackCounter.backCounter()
  117. # BackCounter.paths.append("BaCo")
  118. # toReturn.append(BackCounter)
  119. # print BackCounter.dictKey()
  120. return toReturn
  121. def dictKey(self):
  122. toReturn = []
  123. toReturn.extend(self.top.face)
  124. toReturn.extend(self.bottom.face)
  125. toReturn.extend(self.left.face)
  126. toReturn.extend(self.right.face)
  127. toReturn.extend(self.front.face)
  128. toReturn.extend(self.back.face)
  129. return ''.join(toReturn)
  130. def goalCheck():
  131. return top.allSameColor() and bottom.allSameColor() and left.allSameColor() and right.allSameColor() and front.allSameColor() and back.allSameColor()
  132. class RubikCube:
  133. def solve(self):
  134. Cube = Rubik()
  135. f = open(sys.argv[1], "r")
  136. #Tried to refactor this but got a bunch of global var errors? weird.
  137. Cube.back.face = f.readline().split()
  138. Cube.back.face.extend(f.readline().split())
  139. Cube.back.face.extend(f.readline().split())
  140. Cube.left.face = f.readline().split()
  141. Cube.left.face.extend(f.readline().split())
  142. Cube.left.face.extend(f.readline().split())
  143. Cube.top.face = f.readline().split()
  144. Cube.top.face.extend(f.readline().split())
  145. Cube.top.face.extend(f.readline().split())
  146. Cube.right.face = f.readline().split()
  147. Cube.right.face.extend(f.readline().split())
  148. Cube.right.face.extend(f.readline().split())
  149. Cube.front.face = f.readline().split()
  150. Cube.front.face.extend(f.readline().split())
  151. Cube.front.face.extend(f.readline().split())
  152. Cube.bottom.face = f.readline().split()
  153. Cube.bottom.face.extend(f.readline().split())
  154. Cube.bottom.face.extend(f.readline().split())
  155. f.close()
  156. openList = Cube.successors()
  157. closeList = {}
  158. closeList[Cube.dictKey()] = Cube
  159. while len(openList) > 0:
  160. newCube = openList.pop()
  161. print newCube.dictKey()
  162. if closeList.has_key(newCube.dictKey()) or (len(newCube.paths) == 20):
  163. continue
  164. else:
  165. closeList[newCube.dictKey()] = newCube
  166. if newCube.goalCheck():
  167. return ', '.join(newCube.paths)
  168. else:
  169. for successor in newCube.successors():
  170. if not closeList.has_key(successor.dictKey()):
  171. openList.append(successor)
  172. return 'Done'
  173. ### Transformations ####
  174. def topCounter(cube):
  175. cube.top.rotateCounter()
  176. temp1 = cube.front.face[0]
  177. temp2 = cube.front.face[1]
  178. temp3 = cube.front.face[2]
  179. cube.front.face[0] = cube.left.face[2]
  180. cube.front.face[1] = cube.left.face[5]
  181. cube.front.face[2] = cube.left.face[8]
  182. cube.left.face[2] = cube.back.face[8]
  183. cube.left.face[5] = cube.back.face[7]
  184. cube.left.face[8] = cube.back.face[6]
  185. cube.back.face[8] = cube.right.face[6]
  186. cube.back.face[7] = cube.right.face[3]
  187. cube.back.face[6] = cube.right.face[0]
  188. cube.right.face[6] = temp1
  189. cube.right.face[3] = temp2
  190. cube.right.face[0] = temp3
  191. def topClock(cube):
  192. cube.top.rotateClock()
  193. temp1 = cube.front.face[0]
  194. temp2 = cube.front.face[1]
  195. temp3 = cube.front.face[2]
  196. cube.front.face[0] = cube.right.face[0]
  197. cube.front.face[1] = cube.right.face[3]
  198. cube.front.face[2] = cube.right.face[6]
  199. cube.right.face[0] = cube.back.face[6]
  200. cube.right.face[3] = cube.back.face[7]
  201. cube.right.face[6] = cube.back.face[8]
  202. cube.back.face[6] = cube.left.face[8]
  203. cube.back.face[7] = cube.left.face[5]
  204. cube.back.face[8] = cube.left.face[2]
  205. cube.left.face[8] = temp3
  206. cube.left.face[5] = temp2
  207. cube.left.face[2] = temp1
  208. def leftForward():
  209. left.rotateClock()
  210. temp1 = front.face[0]
  211. temp2 = front.face[3]
  212. temp3 = front.face[6]
  213. front.face[0] = top.face[0]
  214. front.face[3] = top.face[3]
  215. front.face[6] = top.face[6]
  216. top.face[0] = back.face[0]
  217. top.face[3] = back.face[3]
  218. top.face[6] = back.face[6]
  219. back.face[0] = bottom.face[0]
  220. back.face[3] = bottom.face[3]
  221. back.face[6] = bottom.face[6]
  222. bottom.face[0] = temp1
  223. bottom.face[3] = temp2
  224. bottom.face[6] = temp3
  225. def leftBackward():
  226. left.rotateCounter()
  227. temp1 = front.face[0]
  228. temp2 = front.face[3]
  229. temp3 = front.face[6]
  230. front.face[0] = bottom.face[0]
  231. front.face[3] = bottom.face[3]
  232. front.face[6] = bottom.face[6]
  233. bottom.face[0] = back.face[0]
  234. bottom.face[3] = back.face[3]
  235. bottom.face[6] = back.face[6]
  236. back.face[0] = top.face[0]
  237. back.face[3] = top.face[3]
  238. back.face[6] = top.face[6]
  239. top.face[0] = temp1
  240. top.face[3] = temp2
  241. top.face[6] = temp3
  242. def rightForward():
  243. right.rotateCounter()
  244. temp1 = front.face[2]
  245. temp2 = front.face[5]
  246. temp3 = front.face[8]
  247. front.face[2] = top.face[2]
  248. front.face[5] = top.face[5]
  249. front.face[8] = top.face[8]
  250. top.face[2] = back.face[2]
  251. top.face[5] = back.face[5]
  252. top.face[8] = back.face[8]
  253. back.face[2] = bottom.face[2]
  254. back.face[5] = bottom.face[5]
  255. back.face[8] = bottom.face[8]
  256. bottom.face[2] = temp1
  257. bottom.face[5] = temp2
  258. bottom.face[8] = temp3
  259. def rightBackward():
  260. right.rotateClock()
  261. temp1 = front.face[2]
  262. temp2 = front.face[5]
  263. temp3 = front.face[8]
  264. front.face[2] = bottom.face[2]
  265. front.face[5] = bottom.face[5]
  266. front.face[8] = bottom.face[8]
  267. bottom.face[2] = back.face[2]
  268. bottom.face[5] = back.face[5]
  269. bottom.face[8] = back.face[8]
  270. back.face[2] = top.face[2]
  271. back.face[5] = top.face[5]
  272. back.face[8] = top.face[8]
  273. top.face[2] = temp1
  274. top.face[5] = temp2
  275. top.face[8] = temp3
  276. def bottomCounter():
  277. bottom.rotateCounter()
  278. temp1 = front.face[6]
  279. temp2 = front.face[7]
  280. temp3 = front.face[8]
  281. front.face[6] = left.face[0]
  282. front.face[7] = left.face[3]
  283. front.face[8] = left.face[6]
  284. left.face[0] = back.face[2]
  285. left.face[3] = back.face[1]
  286. left.face[6] = back.face[0]
  287. back.face[2] = right.face[8]
  288. back.face[1] = right.face[5]
  289. back.face[0] = right.face[2]
  290. right.face[8] = temp1
  291. right.face[5] = temp2
  292. right.face[2] = temp3
  293. def bottomClock():
  294. bottom.rotateClock()
  295. temp1 = front.face[6]
  296. temp2 = front.face[7]
  297. temp3 = front.face[8]
  298. front.face[6] = right.face[8]
  299. front.face[7] = right.face[5]
  300. front.face[8] = right.face[2]
  301. right.face[8] = back.face[2]
  302. right.face[5] = back.face[1]
  303. right.face[2] = back.face[0]
  304. back.face[2] = left.face[0]
  305. back.face[1] = left.face[3]
  306. back.face[0] = left.face[6]
  307. left.face[0] = temp1
  308. left.face[3] = temp2
  309. left.face[6] = temp3
  310. def frontClock():
  311. front.rotateClock()
  312. temp1 = top.face[6]
  313. temp2 = top.face[7]
  314. temp3 = top.face[8]
  315. top.face[6] = left.face[6]
  316. top.face[7] = left.face[7]
  317. top.face[8] = left.face[8]
  318. left.face[6] = bottom.face[2]
  319. left.face[7] = bottom.face[1]
  320. left.face[8] = bottom.face[0]
  321. bottom.face[2] = right.face[6]
  322. bottom.face[1] = right.face[7]
  323. bottom.face[0] = right.face[8]
  324. right.face[6] = temp1
  325. right.face[7] = temp2
  326. right.face[8] = temp3
  327. def frontCounter():
  328. front.rotateCounter()
  329. temp1 = top.face[6]
  330. temp2 = top.face[7]
  331. temp3 = top.face[8]
  332. top.face[6] = right.face[6]
  333. top.face[7] = right.face[7]
  334. top.face[8] = right.face[8]
  335. right.face[6] = bottom.face[2]
  336. right.face[7] = bottom.face[1]
  337. right.face[8] = bottom.face[0]
  338. bottom.face[2] = left.face[6]
  339. bottom.face[1] = left.face[7]
  340. bottom.face[0] = left.face[8]
  341. left.face[6] = temp1
  342. left.face[7] = temp2
  343. left.face[8] = temp3
  344. def backClock():
  345. back.rotateCounter()
  346. temp1 = top.face[0]
  347. temp2 = top.face[1]
  348. temp3 = top.face[2]
  349. top.face[0] = left.face[0]
  350. top.face[1] = left.face[1]
  351. top.face[2] = left.face[2]
  352. left.face[0] = bottom.face[6]
  353. left.face[1] = bottom.face[7]
  354. left.face[2] = bottom.face[8]
  355. bottom.face[6] = right.face[2]
  356. bottom.face[7] = right.face[1]
  357. bottom.face[8] = right.face[0]
  358. right.face[2] = temp3
  359. right.face[1] = temp2
  360. right.face[0] = temp1
  361. def backCounter():
  362. back.rotateClock()
  363. temp1 = top.face[0]
  364. temp2 = top.face[1]
  365. temp3 = top.face[2]
  366. top.face[0] = right.face[0]
  367. top.face[1] = right.face[1]
  368. top.face[2] = right.face[2]
  369. right.face[0] = bottom.face[8]
  370. right.face[1] = bottom.face[7]
  371. right.face[2] = bottom.face[6]
  372. bottom.face[8] = left.face[2]
  373. bottom.face[7] = left.face[1]
  374. bottom.face[6] = left.face[0]
  375. left.face[2] = temp3
  376. left.face[1] = temp2
  377. left.face[0] = temp1
  378. if __name__=="__main__":
  379. c = RubikCube()
  380. print c.solve()