def two_way_trans(forward_state, backward_state, depth): if depth > 15: return None, None if depth % 2 == 0: for iterator in forward_state.keys(): if backward_state.get(iterator) != None: return forward_state[iterator], backward_state[iterator] for action in actions: new_state = rubik.perm_apply(action, iterator) if forward_state.get(new_state) is None: forward_state[new_state] = forward_state[iterator] + [ action ] return two_way_trans(forward_state, backward_state, depth + 1) else: for iterator in backward_state.keys(): if forward_state.get(iterator) != None: return forward_state[iterator], backward_state[iterator] for action in actions: new_state = rubik.perm_apply(action, iterator) if backward_state.get(new_state) is None: backward_state[new_state] = backward_state[iterator] + [ action ] return two_way_trans(forward_state, backward_state, depth + 1)
def shortest_path_optmized(start, end): """ For Question 2, using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ movesStart = dict() movesStart[start] = [] movesEnd = dict() movesEnd[end] = [] qStart = collections.deque() qEnd = collections.deque() qStart.append(start) qEnd.append(end) found = False finalMoves = [] while (len(qStart) != 0 and len(qEnd) != 0 and not found): s = qStart.popleft() e = qEnd.popleft() m = movesStart[s] n = movesEnd[e] if len(m) > 8 and len(n) > 8: break if s == end: finalMoves = m found = True break if s in movesEnd: finalMoves = m + movesEnd[s][::-1] found = True break if e in movesStart: finalMoves = movesStart[e] + n[::-1] found = True break for i in range(6): x = rubik.perm_apply(rubik.quarter_twists[i], s) y = rubik.perm_apply(rubik.quarter_twists[i], e) if x not in movesStart: qStart.append(x) movesStart[x] = m + [ rubik.quarter_twists_names[rubik.quarter_twists[i]] ] if y not in movesEnd: qEnd.append(y) movesEnd[y] = n + [ rubik.quarter_twists_names[rubik.perm_inverse( rubik.quarter_twists[i])] ] if found: sys.stdout.write(str(finalMoves) + "\n") return finalMoves else: sys.stdout.write(str("No solution\n")) return [None]
def test_shortest_path_2(self): """ Length 2 path.""" start = rubik.I middle = rubik.perm_apply(rubik.F, start) end = rubik.perm_apply(rubik.L, middle) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 2) self.assertEqual(ans, [rubik.F, rubik.L])
def adj(u, dir): adj_u = [] for move in rubik.quarter_twists: if(dir): adj_u.append(rubik.perm_apply(move, u)) else: adj_u.append(rubik.perm_apply(rubik.perm_inverse(move), u)) return adj_u
def testShortestPath2(self): """Length 2 path.""" start = rubik.I middle = rubik.perm_apply(rubik.F, start) end = rubik.perm_apply(rubik.L, middle) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 2) self.assertEqual(ans, [rubik.F, rubik.L])
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. Assumes the rubik.quarter_twists move set. """ moves = rubik.quarter_twists # These dictionaries will have positions as keys, and # (parent_position, move_used_to_reach_position) as values. start_parent = {} # For BFS starting at start end_parent = {} # For BFS starting at end start_current_level_positions = set() end_current_level_positions = set() start_parent[start] = None start_current_level_positions.add(start) end_parent[end] = None end_current_level_positions.add(end) if end in start_parent: # Check if we're done. return calculate_path(start_parent, end_parent, end) for i in range(7): # Because we know the diameter is 14, we don't need more than # 7 iterations from each side. # Expand from start. start_next_level_positions = set() for position in start_current_level_positions: for move in moves: next_position = rubik.perm_apply(move, position) if next_position not in start_parent: start_parent[next_position] = (position, move) start_next_level_positions.add(next_position) if next_position in end_parent: # Check if we're done. return calculate_path(start_parent, end_parent, next_position) start_current_level_positions = start_next_level_positions # Expand from end. end_next_level_positions = set() for position in end_current_level_positions: for move in moves: next_position = rubik.perm_apply(move, position) if next_position not in end_parent: end_parent[next_position] = (position, move) end_next_level_positions.add(next_position) if next_position in start_parent: # Check if we're done. return calculate_path(start_parent, end_parent, next_position) end_current_level_positions = end_next_level_positions return None # There is no path from start to end
def find_move(u, v, dir): for move in rubik.quarter_twists: if(dir): if v == rubik.perm_apply(move, u): return move else: if v == rubik.perm_apply(rubik.perm_inverse(move), u): return move return -1
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ left_checked = {} right_checked = {} left_current = {start: []} right_current = {end: []} left_new = {} right_new = {} left_depth = 0 right_depth = 0 while left_depth < 8: for x in left_current.keys(): y = right_current.get(x, None) if y is not None: ans = left_current[x] + [ rubik.perm_inverse(move) for move in reversed(y) ] return ans for x in left_current.keys(): for move in rubik.quarter_twists: r = rubik.perm_apply(move, x) if not left_checked.get(r, None) and not left_current.get( r, None): left_new[r] = left_current[x] + [move] left_checked[x] = left_current[x] left_current = left_new left_new = {} left_depth += 1 while right_depth < 8: for x in right_current.keys(): y = left_current.get(x, None) if y is not None: ans = y + [ rubik.perm_inverse(move) for move in reversed(right_current[x]) ] return ans for x in right_current.keys(): for move in rubik.quarter_twists: r = rubik.perm_apply(move, x) if not right_checked.get(r, None) and not right_current.get( r, None): right_new[r] = right_current[x] + [move] right_checked[x] = right_current[x] right_current = right_new right_new = {} right_depth += 1 return None
def test_shortest_path_3(self): """ Length 3 path.""" start = rubik.I middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.F, middle1) end = rubik.perm_apply(rubik.Li, middle2) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 3) self.assert_good_path(start, end, ans)
def shortest_path_optmized(start, end): """ For Question 2, using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ q_front = Queue.Queue() q_front.put([start, []]) visited_front = {start: []} q_back = Queue.Queue() q_back.put([end, []]) visited_back = {end: []} if start == end: print([]) return [] while not q_back.empty() or not q_front.empty(): if not q_front.empty(): cur_front = q_front.get() for twist in rubik.quarter_twists: x = (rubik.perm_apply(twist, cur_front[0]), cur_front[1] + [rubik.quarter_twists_names[twist]]) if x[0] in visited_back: print(x[1] + visited_back[x[0]][::-1]) return x[1] + visited_back[x[0]][::-1] if x[0] not in visited_front: visited_front[x[0]] = x[1][:] if len(x[1]) <= 7: q_front.put(x) if not q_back.empty(): cur_back = q_back.get() for twist in rubik.quarter_twists: x = (rubik.perm_apply(twist, cur_back[0]), cur_back[1] + [reversal_name(rubik.quarter_twists_names[twist])]) if x[0] in visited_front: print(visited_front[x[0]] + x[1][::-1]) return visited_front[x[0]] + x[1][::-1] if x[0] not in visited_back: visited_back[x[0]] = x[1][:] if len(x[1]) <= 7: q_back.put(x) print("None")
def testShortestPath3(self): """Length 3 path.""" start = rubik.I middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.F, middle1) end = rubik.perm_apply(rubik.Li, middle2) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 3) self.assertGoodPath(start, end, ans)
def testShortestPath4(self): """Length 4 path.""" start = rubik.I middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.L, middle1) middle3 = rubik.perm_apply(rubik.F, middle2) end = rubik.perm_apply(rubik.L, middle3) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 4) self.assertGoodPath(start, end, ans)
def testShortestPath3(self): """Length 3 path.""" start = rubik.I middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.F, middle1) end = rubik.perm_apply(rubik.Li, middle2) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 3) self.assertGoodPath(start, end, ans) print("Test 4 Pass")
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ moves = rubik.quarter_twists parentS = {} parentE = {} parentS[start] = None parentE[end] = None start_current_positions = set() end_current_positions = set() start_current_positions.add(start) end_current_positions.add(end) if end in parentS: return get_moves(parentS, parentE, end) for i in range(7): start_next_positions = set() for position in start_current_positions: for move in moves: next_position = rubik.perm_apply(move, position) if next_position not in parentS: parentS[next_position] = (position, move) start_next_positions.add(next_position) if next_position in parentE: return get_moves(parentS, parentE, next_position) start_current_positions = start_next_positions end_next_positions = set() for position in end_current_positions: for move in moves: next_position = rubik.perm_apply(move, position) if next_position not in parentE: parentE[next_position] = (position, move) end_next_positions.add(next_position) if next_position in parentS: return get_moves(parentS, parentE, next_position) end_current_positions = end_next_positions return None
def test(x): l = [rubik.L, rubik.F, rubik.Fi, rubik.Li, rubik.Ui] t = { "L": rubik.L, "F": rubik.F, "Fi": rubik.Fi, "Li": rubik.Li, "Ui": rubik.Ui, "U": rubik.U } start = (6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) end = (6, 7, 8, 0, 1, 2, 9, 10, 11, 3, 4, 5, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23) for i in range(x): end = rubik.perm_apply(l[random.randrange(0, len(l))], end) print("\nRunning Test Case") print("start = " + str(start)) print("end = " + str(end)) start_time = time.time() ans1 = shortest_path_optmized(start, end) end_time = time.time() current = start for move in ans1: current = rubik.perm_apply(t[move], current) if (current != end): print(start, end, "Optimised failed") exit() else: print("Optimised ok | Time Taken:" + str(round(end_time - start_time, 2))) #bruteforce will take large time otherwise # if(len(ans1)>6): # return start_time = time.time() ans2 = shortest_path(start, end) end_time = time.time() current = start for move in ans2: current = rubik.perm_apply(t[move], current) if (current != end): print(start, end, "Bruteforce failed") exit() else: print("Bruteforce ok | Time Taken: " + str(round(end_time - start_time, 2)))
def shortest_path(start, end): """ For Question 1, using BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ visited_nodes = {} # initialize visited_nodes[start] = 0 move_recovery = {} move_recovery[start] = {None, None} queue = __import__('collections').deque() queue.append(start) u = None while (len(queue)>0): u = queue.popleft() if (u == end): break if (visited_nodes[u] > 14): # no solution return None # all neighbours of u for moves in rubik.quarter_twists: v = rubik.perm_apply(moves, u) if not(v in visited_nodes): visited_nodes[v] = visited_nodes[u] + 1 move_recovery[v] = (u, moves) queue.append(v) if u != end: return None ans = [] #retrace the moves ptr = end while (ptr != start): ans.append(move_recovery[ptr][1]) ptr = move_recovery[ptr][0] ans = ans[::-1] cube = start[:] for move in ans: cube = rubik.perm_apply(move, cube) assert cube == end return [rubik.quarter_twists_names[x] for x in ans]
def shortest_path_optmized(start, end): q1 = deque() q2 = deque() visited1 = {} visited2 = {} path1 = {} path2 = {} visited1[start] = 1 visited2[end] = 1 path1[start] = [] path2[end] = [] q1.append(start) q2.append(end) while (q1 and q2): curr1 = q1[0] curr2 = q2[0] q1.popleft() q2.popleft() for i in rubik.quarter_twists: p1 = rubik.perm_apply(curr1, i) if (visited1.has_key(p1) == False): visited1[p1] = 1 path1[p1] = path1[curr1] + [rubik.quarter_twists_names[i]] #print(rubik.quarter_twists_names[i]) q1.append(p1) if (visited2.has_key(p1) == True): return path1[p1] + path2[p1] for i in rubik.quarter_twists: p2 = rubik.perm_apply(curr2, i) if (visited2.has_key(p2) == False): visited2[p2] = 1 path2[p2] = [ rubik.quarter_twists_names[rubik.perm_inverse(i)] ] + path2[curr2] #print(rubik.quarter_twists_names[i]) q2.append(p2) if (visited1.has_key(p2) == True): return path1[p2] + path2[p2] return [] """ For Question 2, using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ raise NotImplementedError
def returnmid(): level=1 while(1): if level>7: return None a=q.dequeue() while(a!=None): for i in range(6): b=r.perm_apply(r.quarter_twists[i],a.tuple) k=0 if hash1.search(b): k=1 if k==0: s=state(b) s.parent=a q.enqueue(s) hash1.insert(s) for i in range(len(hash2.l[hashf(b)])): if b==hash2.l[hashf(b)][i].tuple: hash2.l[hashf(b)][i].parent=a return hash2.l[hashf(b)][i] a=q.dequeue() q.enqueue(None) c=p.dequeue() while(c!=None): for i in range(6): d=r.perm_apply(r.quarter_twists[i],c.tuple) k=0 if hash2.search(d): k=1 if k==0: s=state(d) s.child=c p.enqueue(s) hash2.insert(s) for i in range(len(hash1.l[hashf(d)])): if d==hash1.l[hashf(d)][i].tuple: hash1.l[hashf(d)][i].child=c return hash1.l[hashf(d)][i] c=p.dequeue() p.enqueue(None) level+=1
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ level = {start:0} backLevel = {end:0} parent = {start:None} backParent = {end:None} i = 1 frontier = [start] solution = [] backFrontier = [end] connected = False connections = [] while (not connected) and (i <= 7): # explore graph next = [] for u in frontier: # move forwards for move in rubik.quarter_twists: v = rubik.perm_apply(move,u) if v not in level: level[v] = i parent[v] = (u,move) next.append(v) frontier = next backNext = [] for u in backFrontier: # move backwards for move in rubik.quarter_twists: v = rubik.perm_apply(move,u) if v not in backLevel: backLevel[v] = i backParent[v] = (u,rubik.perm_inverse(move)) backNext.append(v) backFrontier = backNext for config in level.keys(): # check for a solution if config in backLevel: connected = True connections.append(config) i += 1 if not connected: # we have explored all options and found no solution return None minConn = findShortestPath(connections,level,backLevel) buildSolution(level,parent,minConn,solution,'forwards') buildSolution(backLevel,backParent,minConn,solution,'backwards') return solution
def shortest_path(start, end): """ For Question 1, using BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ q = deque() visited = {} path = {} visited[start] = 1 path[start] = [] q.append(start) while(q): curr = q[0] q.popleft() for i in rubik.quarter_twists: p = rubik.perm_apply(curr,i) if(visited.has_key(p)==False): visited[p]=1 path[p] = path[curr]+[rubik.quarter_twists_names[i]] #print(rubik.quarter_twists_names[i]) q.append(p) if(p==end): return path[p] return []
def next_frontier(frontier, p_nodes): starting_order = frontier[0].order """ Invariant: At each iteration, we are looking at the nodes in the frontier of the same order as starting_order Initialization: The order of the frontier node is the same as starting_order Maintenance: Given that the starting_order and frontier node order is the same, the loop will continue Termination: The order of the frontier no longer equals the order we want to look at """ while starting_order == frontier[0].order: elm = frontier.popleft() """ Invariant: At each iteration, the position of move in quarter_twists is less than the len(quarter_twists) Initialization: There are moves in quarter_twists Maintenance: Given that there are still moves in quarter_twists to go through, the loop will continue and apply the permutation to the node and add the permutation to the frontier if it doesn't already exist Termination: We have gone through the entire tuple of twists """ # Changes the rubik state for move in rubik.quarter_twists: move_st = rubik.perm_apply(move, elm.st) # Checks to see if the new move_st is not in the nodes list if move_st not in p_nodes: # new node_info with the new move_st, the move command it took # frontier that was popped, and the new depth of node new_st = node_info(move_st, (move, elm), elm.order + 1) frontier.append(new_st) p_nodes.append(move_st)
def process(u, parent, next_): for move in rubik.quarter_twists: v = rubik.perm_apply(move, u) if v not in parent: ## parent[v]=(rubik.perm_inverse(move),move,u) #u parent[v] = (move, u) #u next_.append(v)
def testShortestPath1(self): """Length 1 path.""" start = rubik.I end = rubik.perm_apply(rubik.F, start) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 1) self.assertEqual(ans, [rubik.F])
def test_shortest_path_1(self): """ Length 1 path.""" start = rubik.I end = rubik.perm_apply(rubik.F, start) ans = solver.shortest_path(start, end) self.assertEqual(len(ans), 1) self.assertEqual(ans, [rubik.F])
def shortest_path(start, end): """ For Question 1, using BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ L = Queue.Queue() L.put([start, []]) visited = {start} mov = None while not L.empty(): cur = L.get() if cur[0] == end: mov = cur[1] break for twist in rubik.quarter_twists: x = (rubik.perm_apply(twist, cur[0]), cur[1] + [rubik.quarter_twists_names[twist]]) if x[0] not in visited: visited.add(x[0]) L.put(x) print(mov) return mov
def rubik_list_states(start): """ Gives all the states of the rubiks during solution rather than what twists to make.""" path_twists = bidirectional_bfs_search(start) rubik_configs = [start] for twist in path_twists: rubik_configs.append(perm_apply(twist, rubik_configs[-1])) return rubik_configs
def shortest_path(start, end): if start == end: return [] fparents = {start: None} bparents = {end: None} fmoves = {} bmoves = {} for move in rubik.quarter_twists: fmoves[move] = move bmoves[rubik.perm_inverse(move)] = move forward = (fmoves, fparents, bparents) backward = (bmoves, bparents, fparents) queue = deque([(start, forward), (end, backward), None]) for i in xrange(7): while True: vertex = queue.popleft() if vertex is None: queue.append(None) break position = vertex[0] moves, parents, other_parents = vertex[1] for move in moves: nextp = rubik.perm_apply(move, position) if nextp not in parents: parents[nextp] = (moves[move], position) queue.append((nextp, vertex[1])) if nextp in other_parents: forwardp = path(nextp, fparents) backwardp = path(nextp, bparents) forwardp.reverse() return forwardp + backwardp return None
def shortest_path(start, end): """ For Question 1, using BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ moves = dict() moves[start] = [] finalm = [] q = collections.deque([start]) found = False while (len(q) != 0 and not found): s = q.popleft() m = moves[s] if s == end: found = True finalm = m break for i in range(6): x = rubik.perm_apply(rubik.quarter_twists[i], s) if x not in moves: q.append(x) moves[x] = m + [ rubik.quarter_twists_names[rubik.quarter_twists[i]] ] if found: sys.stdout.write(str(finalm) + "\n") return finalm else: sys.stdout.write(str("No solution\n")) return [None]
def BFS(frontier, dic, lis): for pos in frontier: for turn in rubik.quarter_twists: new_config=rubik.perm_apply(turn,pos) if dic.get(new_config, False): continue dic[new_config]={'parent':pos,'move':turn} lis.append(new_config)
def testShortestPath1(self): """Length 1 path.""" start = rubik.I end = rubik.perm_apply(rubik.F, start) ans = solver.shortest_path(start, end) # print 'ans ',ans, 'has length',len(ans) self.assertEqual(len(ans), 1) self.assertEqual(ans, [rubik.F])
def _path(start, end, moves, rev_edge_func): p = [] cur = end while moves[cur]: move_before = moves[cur] p.append(move_before) # Apply the inverse of the move before to get to the previous state. cur = perm_apply(rev_edge_func(move_before), cur) return p[::-1]
def neighborsMovePairs(position): nbMovePairs=[] for twist in rubik.quarter_twists: # print "apply twist " + rubik.quarter_twists_names[twist] # + "i.e. " + rubik.perm_to_string + "to "+ "position u" neighbor=rubik.perm_apply(twist, position) move=twist nbMovePairs.append((neighbor,move)) return nbMovePairs
def check(start, end, sol): for i in sol: x = rubik.quarter_twists_names.keys()[ rubik.quarter_twists_names.values().index(i)] start = rubik.perm_apply(x, start) if start == end: sys.stdout.write("Correct\n") else: sys.stdout.write("Wrong\n")
def verify(start, end, solution): if solution is None: return for i in solution: start = rubik.perm_apply(X[i], start) if start == end: print("Verification: Correct Solution") else: print("Verification: Incorrect Solution")
def shortest_path(start, end): M = [] # Moves P = {start: "START"} # Parent Q = deque() # Queue F = False # Flag if start == end: return M Q.append(start) while len(Q) > 0 and F == False: # BFS x = Q.popleft() for i in range(6): p = rubik.quarter_twists[i] y = rubik.perm_apply(p, x) if y not in P: Q.append(y) P[y] = i if y == end: F = True break if F == False: # Back-Tracking to generate solution M = None else: z = end while P[z] != "START": c = rubik.quarter_twists[P[z]] if P[z] % 2 == 0: # F, L, U n = rubik.quarter_twists[P[z] + 1] else: # Fi, Li, Ui n = rubik.quarter_twists[P[z] - 1] M.append(rubik.quarter_twists_names[c]) z = rubik.perm_apply(n, z) if (M != None): M = M[::-1] return M
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ if start == end: return [] forward = ([start], {start : []}) backward = ([end], {end : []}) for iter in range(7): (forward_states, forward_moves) = forward (backward_states, backward_moves) = backward next_forward_states = [] for state in forward_states: moves = forward_moves[state] for twist in rubik.quarter_twists: next_state = rubik.perm_apply(twist, state) if next_state in backward_moves: return moves + [twist] + backward_moves[next_state] if not next_state in forward_moves: next_forward_states.append(next_state) forward_moves[next_state] = moves + [twist] next_backward_states = [] for state in backward_states: moves = backward_moves[state] for twist in rubik.quarter_twists: next_state = rubik.perm_apply(rubik.perm_inverse(twist), state) if next_state in forward_moves: return forward_moves[next_state] + [twist] + moves if not next_state in backward_moves: next_backward_states.append(next_state) backward_moves[next_state] = [twist] + moves forward = (next_forward_states, forward_moves) backward = (next_backward_states, backward_moves) return None
def count_repetitive_twists(moves): """ When you apply the same twists to a cube over and over again, the cube will eventually return to its original position. This applies each move in moves repeatedly, until the cube returns to its original position, and counts the length of the cycle. """ current_position = rubik.I for count in xrange(1, 100000): for move in moves: current_position = rubik.perm_apply(move, current_position) if(current_position == rubik.I): return count
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ frontier = deque() frontier.append(start) parent = {start: None} ans_found = False while frontier: u = frontier.popleft() if u == end: ans_found = True break for x in xrange(6): temp = rubik.perm_apply(rubik.quarter_twists[x], u) if temp not in parent: parent[temp] = x + 1 if x%2 == 0 else x - 1 frontier.append(temp) ans = deque() if ans_found: m = end j = parent[m] while parent[m] != None: ans.appendleft(rubik.quarter_twists[j + 1 if j%2 == 0 else j - 1]) print(rubik.quarter_twists_names[ans[0]]) m = rubik.perm_apply(rubik.quarter_twists[j], m) j = parent[m] return list(ans) else: return None
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ if start == end: return [] forward_parents = {start: None} backward_parents = {end: None} forward_moves = {} backward_moves = {} for move in rubik.quarter_twists: forward_moves[move] = move backward_moves[rubik.perm_inverse(move)] = move forward = (forward_moves, forward_parents, backward_parents) backward = (backward_moves, backward_parents, forward_parents) queue = deque([(start, forward), (end, backward), None]) for i in range(7): while True: vertex = queue.popleft() if vertex is None: queue.append(None) break position = vertex[0] moves, parents, other_parents = vertex[1] for move in moves: next_position = rubik.perm_apply(move, position) if next_position in parents: continue parents[next_position] = (moves[move], position) queue.append((next_position, vertex[1])) if next_position in other_parents: forward_path = path(next_position, forward_parents) backward_path = path(next_position, backward_parents) backward_path.reverse() return forward_path + backward_path return None
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start to end position. Returns a list of moves and assumes the rubik.quarter_twists move set. """ if start == end: return [] #if no shortest path exists (start==end), return empty list fparents = {start: None} #first half parents sparents = {end: None} #second half parents fmoves = {} #first half moves smoves = {} #second half moves for turn in rubik.quarter_twists: fmoves[turn] = turn #insert forward moves from quarter_twists smoves[rubik.perm_inverse(turn)] = turn #insert reverse moves (starting from second half) forward = (fmoves, fparents, sparents) #set of moves and first/second half parents backward = (smoves, sparents, fparents) #set of inverse moves with first/second half parents Q = deque([(start, forward), (end, backward), None]) #create new deque(quicklist) Q = (first half, second half, None) for x in range(7): #for each move in quarter_twist while True: #loop v = Q.popleft() #return leftmost element from Q if v is None: #if at the end of Q (None) Q.append(None) #add None to Q break #break from loop position = v[0] #set vertex to start or end moves, parents, otherparents = v[1] #set moves, parents, other parents to forward or backward for i in moves: #start two way BFS nextpos = rubik.perm_apply(i, position) #set node to search if nextpos in parents: continue #if node in parents, continue parents[nextpos] = (moves[i], position) #set parent pointer to node, vertex Q.append((nextpos, v[1])) #add expanded search to Q if nextpos in otherparents: #if node discovered in both searches fpath = path(nextpos, fparents) #forward path set with node + parent pointers spath = path(nextpos, sparents) #backward path set with node + parent pointers spath.reverse() #must reverse the inverse path before joining it with forward path return fpath + spath #return list of moves for the shortest path (forward + backward moves) return None #else return None
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ if start == end: return [] startroot = node(start) endroot = node(end) startq = queue([startroot, None]) endq = queue([endroot, None]) starth = [] endh = [] for i in range(0, 335923): starth.append([]) endh.append([]) startd = {} starth[hash(start)] = (start, None, None) endd = {} endh[hash(end)] = (end, None, None) startd[startroot.list] = (startroot.list, startroot.parent, startroot.orientation) endd[endroot.list] = (endroot.list, endroot.parent, endroot.orientation) i = 0 while i < 7: while True: g = startq.dequeue() if g == None: startq.enqueue(None) break if rubik.perm_apply(rubik.F, g.list) is not starth[hash(rubik.perm_apply(rubik.F, g.list))]: g.child[0] = node(rubik.perm_apply(rubik.F, g.list), g.list, rubik.F) starth[hash(rubik.perm_apply(rubik.F, g.list))].append( (rubik.perm_apply(rubik.F, g.list), g.list, rubik.F) ) startq.enqueue(g.child[0]) if rubik.perm_apply(rubik.F, g.list) is endh[hash(rubik.perm_apply(rubik.F, g.list))]: fr = moves(rubik.perm_apply(rubik.F, g.list), starth) br = moves(rubik.perm_apply(rubik.F, g.list), endh) fr.reverse() z = fr + br return z if rubik.perm_apply(rubik.Fi, g.list) is not starth[hash(rubik.perm_apply(rubik.Fi, g.list))]: g.child[1] = node(rubik.perm_apply(rubik.Fi, g.list), g.list, rubik.Fi) starth[hash(rubik.perm_apply(rubik.Fi, g.list))].append( (rubik.perm_apply(rubik.Fi, g.list), g.list, rubik.Fi) ) startq.enqueue(g.child[1]) if rubik.perm_apply(rubik.Fi, g.list) is endh[hash(rubik.perm_apply(rubik.Fi, g.list))]: fr = moves(rubik.perm_apply(rubik.Fi, g.list), starth) br = moves(rubik.perm_apply(rubik.Fi, g.list), endh) fr.reverse() z = fr + br return z if rubik.perm_apply(rubik.L, g.list) is not starth[hash(rubik.perm_apply(rubik.L, g.list))]: g.child[2] = node(rubik.perm_apply(rubik.L, g.list), g.list, rubik.L) starth[hash(rubik.perm_apply(rubik.L, g.list))].append( (rubik.perm_apply(rubik.L, g.list), g.list, rubik.L) ) startq.enqueue(g.child[2]) if rubik.perm_apply(rubik.L, g.list) is endh[hash(rubik.perm_apply(rubik.L, g.list))]: fr = moves(rubik.perm_apply(rubik.L, g.list), starth) br = moves(rubik.perm_apply(rubik.L, g.list), endh) fr.reverse() z = fr + br return z if rubik.perm_apply(rubik.Li, g.list) is not starth[hash(rubik.perm_apply(rubik.Li, g.list))]: g.child[3] = node(rubik.perm_apply(rubik.Li, g.list), g.list, rubik.Li) starth[hash(rubik.perm_apply(rubik.Li, g.list))].append( (rubik.perm_apply(rubik.Li, g.list), g.list, rubik.Li) ) startq.enqueue(g.child[3]) if rubik.perm_apply(rubik.Li, g.list) is endh[hash(rubik.perm_apply(rubik.Li, g.list))]: fr = moves(rubik.perm_apply(rubik.Li, g.list), starth) br = moves(rubik.perm_apply(rubik.Li, g.list), endh) fr.reverse() z = fr + br return z if rubik.perm_apply(rubik.U, g.list) is not starth[hash(rubik.perm_apply(rubik.U, g.list))]: g.child[4] = node(rubik.perm_apply(rubik.U, g.list), g.list, rubik.U) starth[hash(rubik.perm_apply(rubik.U, g.list))].append( (rubik.perm_apply(rubik.U, g.list), g.list, rubik.U) ) startq.enqueue(g.child[4]) if rubik.perm_apply(rubik.U, g.list) is endh[hash(rubik.perm_apply(rubik.U, g.list))]: fr = moves(rubik.perm_apply(rubik.U, g.list), starth) br = moves(rubik.perm_apply(rubik.U, g.list), endh) fr.reverse() z = fr + br return z if rubik.perm_apply(rubik.Ui, g.list) is not starth[hash(rubik.perm_apply(rubik.Ui, g.list))]: g.child[5] = node(rubik.perm_apply(rubik.Ui, g.list), g.list, rubik.Ui) starth[hash(rubik.perm_apply(rubik.Ui, g.list))].append( (rubik.perm_apply(rubik.Ui, g.list), g.list, rubik.Ui) ) startq.enqueue(g.child[5]) if rubik.perm_apply(rubik.Li, g.list) is endh[hash(rubik.perm_apply(rubik.Ui, g.list))]: fr = moves(rubik.perm_apply(rubik.Ui, g.list), starth) br = moves(rubik.perm_apply(rubik.Ui, g.list), endh) fr.reverse() z = fr + br return z while True: k = endq.dequeue() if k == None: endq.enqueue(None) break if ( rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list) is not endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list))] ): k.child[0] = node(rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list), k.list, rubik.F) endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list))].append( (rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list), k.list, rubik.F) ) endq.enqueue(k.child[0]) if ( rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list) is starth[hash(rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list))] ): fr = moves(rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list), starth) br = moves(rubik.perm_apply(rubik.perm_inverse(rubik.F), k.list), endh) fr.reverse() z = fr + br return z if ( rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list) is not endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list))] ): k.child[1] = node(rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list), k.list, rubik.Fi) endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list))] = ( rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list), k.list, rubik.Fi, ) endq.enqueue(k.child[1]) if rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list) is startd: fr = moves(rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list), starth) br = moves(rubik.perm_apply(rubik.perm_inverse(rubik.Fi), k.list), endh) fr.reverse() z = fr + br return z if ( rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list) is not endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list))] ): k.child[2] = node(rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list), k.list, rubik.L) endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list))] = ( rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list), k.list, rubik.L, ) endq.enqueue(k.child[2]) if ( rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list) is starth[hash(rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list))] ): fr = moves(rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list), starth) br = moves(rubik.perm_apply(rubik.perm_inverse(rubik.L), k.list), endh) fr.reverse() z = fr + br return z if ( rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list) is not endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list))] ): k.child[3] = node(rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list), k.list, rubik.Li) endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list))] = ( rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list), k.list, rubik.Li, ) endq.enqueue(k.child[3]) if ( rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list) is starth[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list))] ): fr = moves(rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list), starth) br = moves(rubik.perm_apply(rubik.perm_inverse(rubik.Li), k.list), endh) fr.reverse() z = fr + br return z if ( rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list) is not endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list))] ): k.child[4] = node(rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list), k.list, rubik.U) endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list))] = ( rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list), k.list, rubik.U, ) endq.enqueue(k.child[4]) if ( rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list) is starth[hash(rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list))] ): fr = moves(rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list), starth) br = moves(rubik.perm_apply(rubik.perm_inverse(rubik.U), k.list), endh) fr.reverse() z = fr + br return z if ( rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list) is not endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list))] ): k.child[5] = node(rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list), k.list, rubik.Ui) endh[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list))] = ( rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list), k.list, rubik.Ui, ) endq.enqueue(k.child[5]) if ( rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list) is starth[hash(rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list))] ): fr = moves(rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list), starth) br = moves(rubik.perm_apply(rubik.perm_inverse(rubik.Ui), k.list), endh) fr.reverse() z = fr + br return z i += 1 return None
def insert_e(x,h,arr,ser): if h<8: flag=0 z=rubik.perm_apply(rubik.F,x) x.c1=node(z) y=(hash(z))%100000 for i in range(0,len(ser[y])): if z is ser[y][i]: flag=1 break else: flag=0 if flag==0: ser[y].append(z) arr[h].append(x.c1) x.c1.parent=x x.c1.ht=h z2=rubik.perm_apply(rubik.Fi,x) x.c2=node(z2) flag=0 y=(hash(z2))%100000 for i in range(0,len(ser[y])): if z2 is ser[y][i]: flag=1 break else: flag=0 if flag==0: ser[y].append(z2) arr[h].append(x.c2) x.c2.parent=x x.c2.ht=h z3=rubik.perm_apply(rubik.L,x) x.c3=node(z3) flag=0 y=(hash(z3))%100000 for i in range(0,len(ser[y])): if z3 is ser[y][i]: flag=1 break else: flag=0 if flag==0: ser[y].append(z3) arr[h].append(x.c3) x.c3.parent=x x.c3.ht=h z4=rubik.perm_apply(rubik.Li,x) x.c4=node(z4) flag=0 y=(hash(z4))%100000 for i in range(0,len(ser[y])): if z4 is ser[y][i]: flag=1 break else: flag=0 if flag==0: ser[y].append(z4) arr[h].append(x.c4) x.c4.parent=x x.c4.ht=h z5=rubik.perm_apply(rubik.U,x) x.c5=node(z5) flag=0 y=(hash(z5))%100000 for i in range(0,len(ser[y])): if z5 is ser[y][i]: flag=1 break else: flag=0 if flag==0: ser[y].append(z5) arr[h].append(x.c5) x.c5.parent=x x.c5.ht=h z6=rubik.perm_apply(rubik.Ui,x) x.c6=node(z6) flag=0 y=(hash(z6))%100000 for i in range(0,len(ser[y])): if z6 is ser[y][i]: flag=1 break else: flag=0 if flag==0: ser[y].append(z6) arr[h].append(x.c6) x.c6.parent=x x.c6.ht=h return [arr,ser]
def adjacency(pos): adj_list = [] for t in twists: p = rubik.perm_apply(t, pos) adj_list.append(p) return adj_list
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ if start==end: return [] startroot=node(start) endroot=node(end) startq=queue([startroot,None]) endq=queue([endroot,None]) startd={} startd[start]=(start,None,None) endd={} endd[end]=(end,None,None) i=0 while i<7: while True: g=startq.dequeue() if g==None: startq.enqueue(None) break if rubik.perm_apply(rubik.F,g.list) not in startd: g.child[0]=node(rubik.perm_apply(rubik.F,g.list),g.list,rubik.F) startd[rubik.perm_apply(rubik.F,g.list)]=(rubik.perm_apply(rubik.F,g.list),g.list,rubik.F) startq.enqueue(g.child[0]) if rubik.perm_apply(rubik.F,g.list) in endd: fr=moves(rubik.perm_apply(rubik.F,g.list),startd) br=moves(rubik.perm_apply(rubik.F,g.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.Fi,g.list) not in startd: g.child[1]=node(rubik.perm_apply(rubik.Fi,g.list),g.list,rubik.Fi) startd[rubik.perm_apply(rubik.Fi,g.list)]=(rubik.perm_apply(rubik.Fi,g.list),g.list,rubik.Fi) startq.enqueue(g.child[1]) if rubik.perm_apply(rubik.Fi,g.list) in endd: fr=moves(rubik.perm_apply(rubik.Fi,g.list),startd) br=moves(rubik.perm_apply(rubik.Fi,g.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.L,g.list) not in startd: g.child[2]=node(rubik.perm_apply(rubik.L,g.list),g.list,rubik.L) startd[rubik.perm_apply(rubik.L,g.list)]=(rubik.perm_apply(rubik.L,g.list),g.list,rubik.L) startq.enqueue(g.child[2]) if rubik.perm_apply(rubik.L,g.list) in endd: fr=moves(rubik.perm_apply(rubik.L,g.list),startd) br=moves(rubik.perm_apply(rubik.L,g.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.Li,g.list) not in startd: g.child[3]=node(rubik.perm_apply(rubik.Li,g.list),g.list,rubik.Li) startd[rubik.perm_apply(rubik.Li,g.list)]=(rubik.perm_apply(rubik.Li,g.list),g.list,rubik.Li) startq.enqueue(g.child[3]) if rubik.perm_apply(rubik.Li,g.list) in endd: fr=moves(rubik.perm_apply(rubik.Li,g.list),startd) br=moves(rubik.perm_apply(rubik.Li,g.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.U,g.list) not in startd: g.child[4]=node(rubik.perm_apply(rubik.U,g.list),g.list,rubik.U) startd[rubik.perm_apply(rubik.U,g.list)]=(rubik.perm_apply(rubik.U,g.list),g.list,rubik.U) startq.enqueue(g.child[4]) if rubik.perm_apply(rubik.U,g.list) in endd: fr=moves(rubik.perm_apply(rubik.U,g.list),startd) br=moves(rubik.perm_apply(rubik.U,g.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.Ui,g.list) not in startd: g.child[5]=node(rubik.perm_apply(rubik.Ui,g.list),g.list,rubik.Ui) startd[rubik.perm_apply(rubik.Ui,g.list)]=(rubik.perm_apply(rubik.Ui,g.list),g.list,rubik.Ui) startq.enqueue(g.child[5]) if rubik.perm_apply(rubik.Li,g.list) in endd: fr=moves(rubik.perm_apply(rubik.Ui,g.list),startd) br=moves(rubik.perm_apply(rubik.Ui,g.list),endd) fr.reverse() z=fr+br return z while True: k=endq.dequeue() if k==None: endq.enqueue(None) break if rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list) not in endd: k.child[0]=node(rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list),k.list,rubik.F) endd[rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list)]=(rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list),k.list,rubik.F) endq.enqueue(k.child[0]) if rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list) in startd: fr=moves(rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list),startd) br=moves(rubik.perm_apply(rubik.perm_inverse(rubik.F),k.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list) not in endd: k.child[1]=node(rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list),k.list,rubik.Fi) endd[rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list)]=(rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list),k.list,rubik.Fi) endq.enqueue(k.child[1]) if rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list) in startd: fr=moves(rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list),startd) br=moves(rubik.perm_apply(rubik.perm_inverse(rubik.Fi),k.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list) not in endd: k.child[2]=node(rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list),k.list,rubik.L) endd[rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list)]=(rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list),k.list,rubik.L) endq.enqueue(k.child[2]) if rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list) in startd: fr=moves(rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list),startd) br=moves(rubik.perm_apply(rubik.perm_inverse(rubik.L),k.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list) not in endd: k.child[3]=node(rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list),k.list,rubik.Li) endd[rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list)]=(rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list),k.list,rubik.Li) endq.enqueue(k.child[3]) if rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list) in startd: fr=moves(rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list),startd) br=moves(rubik.perm_apply(rubik.perm_inverse(rubik.Li),k.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list) not in endd: k.child[4]=node(rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list),k.list,rubik.U) endd[rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list)]=(rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list),k.list,rubik.U) endq.enqueue(k.child[4]) if rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list) in startd: fr=moves(rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list),startd) br=moves(rubik.perm_apply(rubik.perm_inverse(rubik.U),k.list),endd) fr.reverse() z=fr+br return z if rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list) not in endd: k.child[5]=node(rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list),k.list,rubik.Ui) endd[rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list)]=(rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list),k.list,rubik.Ui) endq.enqueue(k.child[5]) if rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list) in startd: fr=moves(rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list),startd) br=moves(rubik.perm_apply(rubik.perm_inverse(rubik.Ui),k.list),endd) fr.reverse() z=fr+br return z i+=1 return None
def assertGoodPath(self, start, end, path): current = start for move in path: current = rubik.perm_apply(move, current) self.assertEqual(current, end)
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. You can use the rubik.quarter_twists move set. Each move can be applied using rubik.perm_apply """ if start==end: return [] startroot=node(start) endroot=node(end) startq=queue([startroot,None]) endq=queue([endroot,None]) starth=[] endh=[] for i in range(0,335923): starth.append([]) endh.append([]) starth[hash(start)].append((start,None,None)) endh[hash(end)].append((end,None,None)) #startd[startroot.list]=(startroot.list,startroot.parent,startroot.orientation) #endd[endroot.list]=(endroot.list,endroot.parent,endroot.orientation) move=[rubik.F,rubik.Fi,rubik.L,rubik.Li,rubik.U,rubik.Ui] i=0 while i<7: while True: g=startq.dequeue() if g is None: startq.enqueue(None) break j=0 for k in move: m=rubik.perm_apply(k,g.list) if search(m,starth[hash(m)]) is None: g.child[j]=node(m,g,k) starth[hash(m)].append((m,g,k)) startq.enqueue(g.child[j]) if search(m,endh[hash(m)]) is not None: fr=path(m,starth[hash(m)]) br=path(m,endh[hash(m)]) fr.reverse() return fr + br j+=1 while True: g=endq.dequeue() if g is None: endq.enqueue(None) break j=0 for k in move: m=rubik.perm_apply(rubik.perm_inverse(k),g.list) if search(m,endh[hash(m)]) is None: g.child[j]=node(m,g,k) endh[hash(m)].append((m,g,k)) endq.enqueue(g.child[j]) if search(m,starth[hash(m)]) is not None: fr=path(m,starth[hash(m)]) br=path(m,endh[hash(m)]) fr.reverse() return fr + br j+=1 i+=1 #print i return None
def shortest_path(start, end): """ Using 2-way BFS, finds the shortest path from start_position to end_position. Returns a list of moves. """ if start==end: return [] p=queue() q=queue() hash1=hashtable() hash2=hashtable() s=state(start) hash2.insert(s) p.enqueue(s) p.enqueue(None) s=state(end) hash1.insert(s) q.enqueue(s) q.enqueue(None) def returnmid(): level=1 while(1): if level>7: return None a=q.dequeue() while(a!=None): for i in range(6): b=r.perm_apply(r.quarter_twists[i],a.tuple) k=0 if hash1.search(b): k=1 if k==0: s=state(b) s.parent=a q.enqueue(s) hash1.insert(s) for i in range(len(hash2.l[hashf(b)])): if b==hash2.l[hashf(b)][i].tuple: hash2.l[hashf(b)][i].parent=a return hash2.l[hashf(b)][i] a=q.dequeue() q.enqueue(None) c=p.dequeue() while(c!=None): for i in range(6): d=r.perm_apply(r.quarter_twists[i],c.tuple) k=0 if hash2.search(d): k=1 if k==0: s=state(d) s.child=c p.enqueue(s) hash2.insert(s) for i in range(len(hash1.l[hashf(d)])): if d==hash1.l[hashf(d)][i].tuple: hash1.l[hashf(d)][i].child=c return hash1.l[hashf(d)][i] c=p.dequeue() p.enqueue(None) level+=1 mid=returnmid() x=mid y=mid if mid==None: return None u=[] while x.tuple!=start: for i in range(6): b=r.perm_apply(r.quarter_twists[i],x.tuple) if b==x.child.tuple: if i%2==0: u.append(r.quarter_twists[i+1]) else: u.append(r.quarter_twists[i-1]) break x=x.child path1=u[::-1] v=[] while y.tuple!=end: for i in range(6): b=r.perm_apply(r.quarter_twists[i],y.tuple) if b==y.parent.tuple: v.append(r.quarter_twists[i]) break y=y.parent path2=v path=path1+path2 return path
d=c.orientation c=c.parent return path start=rubik.F '''end=rubik.I start = rubik.I middle = rubik.perm_apply(rubik.F, start) end = rubik.perm_apply(rubik.L, middle) start = rubik.I middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.F, middle1) end = rubik.perm_apply(rubik.Li, middle2) start = rubik.I middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.L, middle1) middle3 = rubik.perm_apply(rubik.F, middle2) end = rubik.perm_apply(rubik.L, middle3) #start = (6, 7, 8, 20, 18, 19, 3, 4, 5, 16, 17, 15, 0, 1, 2, 14, 12, 13, 10, 11, 9, 21, 22, 23) #end = rubik.I #start = (7, 8, 6, 20, 18, 19, 3, 4, 5, 16, 17, 15, 0, 1, 2, 14, 12, 13, 10, 11, 9, 21, 22, 23) #end = rubik.I #start = rubik.I''' middle1 = rubik.perm_apply(rubik.F, start) middle2 = rubik.perm_apply(rubik.L, middle1) middle3 = rubik.perm_apply(rubik.F, middle2) end = rubik.perm_apply(rubik.L, middle3) print shortest_path(start,end)
import rubik twists = ( rubik.F, rubik.L, rubik.Fi, rubik.Li, rubik.U, rubik.Ui, rubik.perm_apply(rubik.F, rubik.F), rubik.perm_apply(rubik.L, rubik.L), rubik.perm_apply(rubik.U, rubik.U) ) def adjacency(pos): adj_list = [] for t in twists: p = rubik.perm_apply(t, pos) adj_list.append(p) return adj_list def positions_at_level(level): """ Using BFS, returns the number of cube configurations that are exactly a given number of levels away from the starting position (rubik.I), using the rubik.quarter_twists move set. """ if level == 0: return i blevel = {rubik.I:0} parent = {rubik.I: None} i = 1 frontier = [rubik.I]