def __init__(self, board): self.board = board self.twin_board = self.board.twin() self.data_structure = DataStructure() self.twin_data_structure = DataStructure() self.states_explored = -1 current_state = self.board current_twin_state = self.twin_board while True: self.states_explored += 1 # print(current_state.moves_to_reach) # print(current_state) if current_state.is_solved(): self.solution = self._form_solution(current_state) break elif current_twin_state.is_solved(): self.moves = -1 self.solution = [] break for neighbor in current_state.neighbors(): if current_state.previous is None or not neighbor.has_same_data(current_state.previous): self.data_structure.add(neighbor) for neighbor in current_twin_state.neighbors(): if current_twin_state.previous is None or not neighbor.has_same_data(current_twin_state.previous): self.twin_data_structure.add(neighbor) current_state = self.data_structure.get_min() current_twin_state = self.twin_data_structure.get_min()
def heapsort(arr): """ Implements heapsort O(n*log(n)) """ heap = Heap(arr) for i in range(heap.size - 1, 0, -1): heap.heap[0], heap.heap[heap.size - 1] = heap.heap[heap.size - 1], heap.heap[0] heap.size -= 1 heap.max_heapify(0) return heap.heap # Ordered array
def heap_sort(num_arr): """ Returns num_arr sorted in ascending fashion. The original array is not modified. Sorting is implemented using heap sort algorithm. The algorithm has O(n * log(n)) complexity. How it works: The array is put into max heap. The root of max heap is always the largest number. The sorting is done by repeated popping of the root. This implementation does not conserve the order of equal elements ("unstable sort"). """ hp = Heap(num_arr) result = [] while not hp.is_empty(): result.insert(0, hp.pop_max()) return result
def test_find_open_with_empty_aunt(self): node17 = HeapNode(17) node15 = HeapNode(15) node11 = HeapNode(11) node6 = HeapNode(6) node10 = HeapNode(10) node17.left = node15 node17.right = node11 node15.left = node6 node15.right = HeapNode(10) heap = Heap(node17) self.assertEqual(heap[-1].value, 10) self.assertEqual(heap.find_open(), (node11, 'left'))
def test_create_many(self): def is_invariant_node(i, my_heap): if i < 0 or i >= my_heap.size: raise IndexError(f"Index i should be between [0 and {my_heap.size})") if i != 0: pt = (i - 1) // 2 if my_heap.arr[pt] < my_heap.arr[i]: return False lf, rt = 2*i + 1, 2*i + 2 if lf >= my_heap.size: return True elif rt == my_heap.size: if my_heap.arr[lf] > my_heap.arr[i]: return False else: if my_heap.arr[i] < max(my_heap.arr[lf], my_heap.arr[rt]): return False return True def check_heap_inv(my_heap): is_invariant = True for i in range(my_heap.size): is_invariant = is_invariant and is_invariant_node(i, my_heap) return is_invariant n_cases = 100 n_nums = 50 for _ in range(n_cases): num_list = list(np.random.rand(n_nums)) h = Heap(num_list) self.assertTrue(check_heap_inv(h), "Heap invariant check failed")
def test_find_open_with_single_child_aunt(self): node17 = HeapNode(17) node15 = HeapNode(15) node11 = HeapNode(11) node6 = HeapNode(6) node10 = HeapNode(10) node7 = HeapNode(7) node17.left = node15 node17.right = node11 node15.left = node6 node15.right = HeapNode(10) node11.left = node7 heap = Heap(node17) self.assertEqual(heap[-1].value, 7) self.assertEqual(heap.find_open(), (node11, 'right'))
def test_create(self): num_list = [1, 4, 7, 5, -3, 2, 8, 9] h = Heap(num_list) result = [9, 5, 8, 4, -3, 2, 7, 1] self.assertTrue(h.arr == result, f"Heap construction failed {h.arr}")
def test_delete(self): # 17 7 15 15 # / \ / \ / \ / \ # 15 11 --> 15 11 --> 7 11 --> 10 11 # / \ / / \ / \ / \ # 6 10 7 6 10 6 10 6 7 heap = Heap(max_heap()) heap[2].value = 11 heap.delete_root() self.assertTrue(test_binary_node(heap.root, 15, 10, 11, None)) self.assertTrue(test_binary_node(heap.root.left, 10, 6, 7, 15)) self.assertTrue(test_binary_node(heap.root.right, 11, None, None, 15)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 10)) self.assertTrue(test_binary_node(heap.root.left.right, 7, None, None, 10)) # 15 7 11 # / \ / \ / \ # 10 11 --> 10 11 --> 10 7 # / \ / / # 6 7 6 6 heap.delete_root() self.assertTrue(test_binary_node(heap.root, 11, 10, 7, None)) self.assertTrue(test_binary_node(heap.root.left, 10, 6, None, 11)) self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 11)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 10)) # 11 6 10 # / \ / \ / \ # 10 7 --> 10 7 --> 6 7 # / # 6 heap.delete_root() self.assertTrue(test_binary_node(heap.root, 10, 6, 7, None)) self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 10)) self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 10)) # 10 7 # / \ --> / # 6 7 6 heap.delete_root() self.assertTrue(test_binary_node(heap.root, 7, 6, None, None)) self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 7)) # 7 # / --> 6 # 6 heap.delete_root() self.assertTrue(test_binary_node(heap.root, 6, None, None, None)) # 6 --> None heap.delete_root() self.assertFalse(heap.root)
def test_insertion_with_percolation(self): # 17 # / \ # 15 10 # / \ / # 6 10 7 # 6 six = HeapNode(6) heap = Heap(six) self.assertTrue(test_binary_node(heap.root, 6, None, None, None)) # 6 10 # / --> / # 10 6 heap.insert(10) self.assertTrue(test_binary_node(heap.root, 10, 6, None, None)) self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 10)) # 10 10 # / \ --> / \ # 6 7 6 7 heap.insert(7) self.assertTrue(test_binary_node(heap.root, 10, 6, 7, None)) self.assertTrue(test_binary_node(heap.root.left, 6, None, None, 10)) self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 10)) # 10 15 # / \ --> / \ # 6 7 10 7 # / / # 15 6 heap.insert(15) self.assertTrue(test_binary_node(heap.root, 15, 10, 7, None)) self.assertTrue(test_binary_node(heap.root.left, 10, 6, None, 15)) self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 15)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 10)) # 15 17 # / \ --> / \ # 10 7 15 7 # / \ / \ # 6 17 6 10 heap.insert(17) self.assertTrue(test_binary_node(heap.root, 17, 15, 7, None)) self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) self.assertTrue(test_binary_node(heap.root.right, 7, None, None, 17)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15)) self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15)) # 17 17 # / \ --> / \ # 15 7 15 11 # / \ / / \ / # 6 10 11 6 10 7 heap.insert(11) self.assertTrue(test_binary_node(heap.root, 17, 15, 11, None)) self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) self.assertTrue(test_binary_node(heap.root.right, 11, 7, None, 17)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15)) self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15)) self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 11))
def test_bubble(self): # 17 17 100 # / \ / \ / \ # 15 10 --> 15 100 --> 15 17 # / \ / \ / \ / \ / \ / \ # 6 10 7 100 6 10 7 10 6 10 7 10 heap = Heap(max_heap()) parent = heap.root.right last = HeapNode(100) parent.right = last last.parent = parent heap.bubble(last) self.assertTrue(test_binary_node(heap.root, 100, 15, 17, None)) self.assertTrue(test_binary_node(heap.root.right, 17, 7, 10, 100)) self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 17)) self.assertTrue(test_binary_node(heap.root.right.right, 10, None, None, 17)) # 100 100 100 # / \ / \ / \ # 15 17 --> 15 17 --> 99 17 # / \ / \ / \ / \ / \ / \ # 6 10 7 10 99 10 7 10 15 10 7 10 # / / / # 99 6 6 parent = heap.root.left.left last = HeapNode(99) last.parent = parent parent.left = last heap.bubble(last) self.assertTrue(test_binary_node(heap.root, 100, 99, 17, None)) self.assertTrue(test_binary_node(heap.root.left, 99, 15, 10, 100)) self.assertTrue(test_binary_node(heap.root.left.left, 15, 6, None, 99)) self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 99)) self.assertTrue(test_binary_node(heap.root.left.left.left, 6, None, None, 15)) # 100 100 100 # / \ / \ / \ # 99 17 --> 99 17 --> 100 17 # / \ / \ / \ / \ / \ / \ # 15 10 7 10 15 100 7 10 15 99 7 10 # / \ / / \ / / \ / # 6 12 100 6 12 10 6 12 10 fifteen = heap.root.left.left twelve = HeapNode(12) twelve.parent = fifteen fifteen.right = twelve ten = heap.root.left.right last = HeapNode(100) ten.left = last last.parent = ten heap.bubble(last) self.assertTrue(test_binary_node(heap.root, 100, 100, 17, None)) self.assertTrue(test_binary_node(heap.root.left, 100, 15, 99, 100)) self.assertTrue(test_binary_node(heap.root.left.left, 15, 6, 12, 100)) self.assertTrue(test_binary_node(heap.root.left.right, 99, 10, None, 100))
def test_insert(self): node17 = HeapNode(17) heap = Heap(node17) heap.insert(15) self.assertTrue(test_binary_node(heap.root, 17, 15, None, None)) self.assertTrue(test_binary_node(heap.root.left, 15, None, None, 17)) heap.insert(10) self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None)) self.assertTrue(test_binary_node(heap.root.left, 15, None, None, 17)) self.assertTrue(test_binary_node(heap.root.right, 10, None, None, 17)) heap.insert(6) self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None)) self.assertTrue(test_binary_node(heap.root.left, 15, 6, None, 17)) self.assertTrue(test_binary_node(heap.root.right, 10, None, None, 17)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15)) heap.insert(10) self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None)) self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) self.assertTrue(test_binary_node(heap.root.right, 10, None, None, 17)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15)) self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15)) heap.insert(7) self.assertTrue(test_binary_node(heap.root, 17, 15, 10, None)) self.assertTrue(test_binary_node(heap.root.left, 15, 6, 10, 17)) self.assertTrue(test_binary_node(heap.root.right, 10, 7, None, 17)) self.assertTrue(test_binary_node(heap.root.left.left, 6, None, None, 15)) self.assertTrue(test_binary_node(heap.root.left.right, 10, None, None, 15)) self.assertTrue(test_binary_node(heap.root.right.left, 7, None, None, 10))
def test_heap_iteration(self): heap = Heap(max_heap()) self.assertEqual([int(str(n)) for n in heap.breadth()], [17, 15, 10, 6, 10, 7]) self.assertEqual([int(str(n)) for n in heap], [17, 15, 10, 6, 10, 7]) self.assertEqual(heap.flatten(), [17, 15, 10, 6, 10, 7])