Advertisement
Guest User

Untitled

a guest
Jun 17th, 2019
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.11 KB | None | 0 0
  1. #######################
  2. #### NRP3finder.py ####
  3. ### Thomas Lam 2018 ###
  4. #######################
  5.  
  6. import copy
  7. from pprint import pprint
  8.  
  9. class Alg(): # An algorithm and corresponding effect
  10. def __init__(self, *args):
  11. if len(args) == 1:
  12. self.board = makeBoard(args[0])
  13. self.moveType = 'x' # RotX or RotY next?
  14. self.moveList = []
  15.  
  16. if len(args) == 3:
  17. self.board = copy.deepcopy(args[0])
  18. self.moveType = args[1]
  19. self.moveList = args[2][:]
  20.  
  21. def move(self, turns):
  22. if self.moveType == 'x':
  23. self.board = rotX(self.board, turns)
  24. self.moveType = 'y'
  25.  
  26. elif self.moveType == 'y':
  27. self.board = rotY(self.board, turns)
  28. self.moveType = 'x'
  29.  
  30. self.moveList.append(turns)
  31.  
  32. def executeMoves(self, moves): # Execute a list of moves in sequence. Syntax: [1,2,3,1,2,1,3, etc.]
  33. for m in moves:
  34. self.move(m)
  35.  
  36. def cloneMove(self, turns): # Clone the algorithm and advance the clone by one move
  37. newAlg = Alg(self.board, self.moveType, self.moveList)
  38. newAlg.move(turns)
  39. return newAlg
  40.  
  41. def permCycleLens(self): # Compute the lengths of all cycles in the algorithm permutation and toss into an array
  42. return cycleLens(collapseBoard(self.board))
  43.  
  44. def has3Cycle(self): # Does it contain a 3 cycle?
  45. return 3 in self.permCycleLens()
  46.  
  47. def hasUnique3Cycle(self): # Does it have a unique 3 cycle?
  48. has3 = False # Does it have a pure 3 cycle?
  49. num3 = 0 # Number of cycles of order divisible by 3
  50. for num in self.permCycleLens():
  51. if num == 3:
  52. has3 = True
  53.  
  54. if num % 3 == 0:
  55. num3 += 1
  56.  
  57. return has3 and num3 == 1
  58.  
  59. def getUnique3Cycle(self):
  60. assert self.hasUnique3Cycle
  61. for cycle in cycleDecompose(collapseBoard(self.board)):
  62. if len(cycle) == 3:
  63. return cycle
  64.  
  65. def getCycles(self):
  66. print cycleDecompose(collapseBoard(self.board))
  67.  
  68. def ppprint(x):
  69. pprint(x, width=40)
  70.  
  71. def makeBoard(b): # Make b+1 x b NRP board
  72. board = []
  73. num = 0
  74. for i in range(b):
  75. row = []
  76. for j in range(b+1):
  77. row.append(num)
  78. num += 1
  79. board.append(row)
  80.  
  81. return board
  82.  
  83. def collapseBoard(board): # List out elements into a 1D array
  84. out = []
  85. for row in board:
  86. for i in row:
  87. out.append(i)
  88.  
  89. return out
  90.  
  91. def cycleLens(arr):
  92. remaining = set(arr)
  93. output = []
  94. while len(remaining) > 0:
  95. length = 1
  96. num = remaining.pop()
  97. while 1:
  98. num = arr[num]
  99. if num not in remaining:
  100. break
  101.  
  102. remaining.remove(num)
  103. length += 1
  104.  
  105. output.append(length)
  106.  
  107. return output
  108.  
  109. def cycleDecompose(arr):
  110. remaining = set(arr)
  111. output = []
  112. while len(remaining) > 0:
  113. num = remaining.pop()
  114. cycle = [num]
  115. while 1:
  116. num = arr[num]
  117. if num not in remaining:
  118. break
  119.  
  120. remaining.remove(num)
  121. cycle.append(num)
  122.  
  123. output.append(cycle)
  124.  
  125. return output
  126.  
  127. def rotX(board, turns = 1):
  128. b = len(board)
  129. newBoard = copy.deepcopy(board)
  130. for i in range(b):
  131. for j in range(b):
  132. if turns == 1:
  133. newBoard[i][j] = board[j][b-1-i]
  134.  
  135. elif turns == 2:
  136. newBoard[i][j] = board[b-1-i][b-1-j]
  137.  
  138. elif turns == 3:
  139. newBoard[i][j] = board[b-1-j][i]
  140.  
  141. return newBoard
  142.  
  143. def rotY(board, turns = 1):
  144. b = len(board)
  145. newBoard = copy.deepcopy(board)
  146. for i in range(b):
  147. for j in range(1,b+1):
  148. if turns == 1:
  149. newBoard[i][j] = board[j-1][b-i]
  150.  
  151. elif turns == 2:
  152. newBoard[i][j] = board[b-1-i][b+1-j]
  153.  
  154. elif turns == 3:
  155. newBoard[i][j] = board[b-j][i+1]
  156.  
  157. return newBoard
  158.  
  159. # Testing
  160.  
  161. testAlg = Alg(3)
  162. testAlg.executeMoves([1,1,1,3,1])
  163.  
  164. assert testAlg.has3Cycle()
  165. assert not testAlg.hasUnique3Cycle()
  166.  
  167. testAlg = Alg(4)
  168. testAlg.move(1)
  169. assert not testAlg.has3Cycle()
  170.  
  171. print 'Congrats! You didn't mess up! Starting search...'
  172.  
  173. # Testing
  174.  
  175. b = int(raw_input('Board size: '))
  176.  
  177. algList = [Alg(b)]
  178.  
  179. found3Cycle = False
  180. foundUnique3Cycle = False
  181.  
  182. while not foundUnique3Cycle:
  183. # Advance all algorithms
  184. newAlgList = []
  185. for alg in algList:
  186. newAlgList.append(alg.cloneMove(1))
  187. newAlgList.append(alg.cloneMove(2))
  188. newAlgList.append(alg.cloneMove(3))
  189.  
  190. algList = copy.deepcopy(newAlgList)
  191.  
  192. # Search for 3-cycles
  193.  
  194. for alg in algList:
  195. if alg.has3Cycle() and not found3Cycle:
  196. print 'Found 3-cycle.'
  197. print alg.moveList
  198. found3Cycle = True
  199.  
  200. if alg.hasUnique3Cycle() and not foundUnique3Cycle:
  201. print 'Found unique 3-cycle.'
  202. print 'Algorithm:',
  203. print alg.moveList
  204. print '3-cycle:',
  205. print alg.getUnique3Cycle()
  206. print 'All cycles:',
  207. print alg.getCycles()
  208. foundUnique3Cycle = True
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement