예제 #1
0
def test_should_check_median_for_given_elements(elements):
    asa = ASA()

    for e in elements:
        asa.insert(e)

    assert asa.median == median(elements)
예제 #2
0
    def draw_insertion_evolution(self, to_insert, name='insertion'):
        asa = ASA()
        evolution = []
        save_kwargs = {
            "format": "GIF",
            "save_all": True,
            "duration": 1000,
            "loop": False,
        }

        added = []

        for el in to_insert:
            asa.insert(el)
            img = self.draw_asa(asa, save=False)
            draw = ImageDraw.Draw(img)
            a_font = ImageFont.truetype(self.font_path, 30)
            draw.text((50, 50), f'Prev: {added}', fill='black', font=a_font)

            el_font = ImageFont.truetype(self.font_path, 50)
            draw.text((50, 120), f'Current {el}', fill='red', font=el_font)

            added.append(el)
            evolution.append(img)

        evolution[0].save(f'{name}.gif',
                          append_images=evolution[1:],
                          **save_kwargs)
예제 #3
0
def test_should_return_false_for_given_asa_trees(elements):
    asa = ASA()

    for e in elements:
        asa.insert(e)
    found, _ = asa.search(10)
    assert found is False
예제 #4
0
def test_asa_with_strings(insert, root, min_, max_):
    asa = ASA()
    for el in insert:
        asa.insert(el)

    assert asa.root.keys[0].key == root
    assert asa.min.key == min_
    assert asa.max.key == max_
예제 #5
0
def test_one_level_asa_tree():
    asa = ASA()
    for i in [2, 5]:
        asa.insert(i)

    assert asa.min == 2
    assert asa.max == 5

    assert asa.root.leaf
    assert asa.root.keys == [2, 5]
예제 #6
0
def test_should_return_element_for_given_asa_trees_and_search_keys(
        elements, key):
    asa = ASA()

    for e in elements:
        asa.insert(e)

    found, _ = asa.search(key)
    assert found
    assert found.key == key
예제 #7
0
def test_insert_should_add_counter_for_keys_in_not_leaf_nodes():
    test_data = [5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4]
    asa = ASA()
    for f_val in test_data:
        asa.insert(f_val)

    results = [(4.400, 1), (4.600, 2), (4.700, 1), (4.900, 2), (5.000, 2),
               (5.100, 1), (5.400, 2)]

    for ind, val in enumerate(asa.sorted_d_queue):
        assert results[ind][0] == val.key and results[ind][1] == val.count
예제 #8
0
def test_should_add_one_key_to_asa_and_properly_initialize_dependent_data_structures(
):
    asa = ASA()
    asa.insert(2)

    assert asa.min == asa.max
    assert asa.min == 2
    assert isinstance(asa.min, ASABaseElem)

    assert asa.root.keys == [2]
    assert asa.root.children == []
    assert asa.root.leaf
예제 #9
0
def test_asa_should_have_proper_parent_element_structure():
    asa = ASA()
    for key in [2, 3, 5, 7, 8, 9, 10, 11]:
        asa.insert(key)

    elem, node = asa.search(11)

    assert node.parent.keys == [9]
    grandparent = node.parent.parent

    assert grandparent == asa.root
    assert asa.root.keys == [7]
예제 #10
0
def test_should_replace_root_when_tree_will_shrink(to_delete, root_keys,
                                                   insertion_order):
    asa = ASA()
    for i in range(7):
        asa.insert(i)

    assert asa.delete(to_delete)
    assert asa.root.keys == root_keys

    asa_after_delete = ASA()
    for el in insertion_order:
        asa_after_delete.insert(el)

    check_structure(asa.root, asa_after_delete.root)
예제 #11
0
def test_delete_should_handle_filing_empty_leaf_for_one_level_tree_and_two_children(
        add, delete, empty_value, ch_index):
    asa = ASA()
    for i in range(3):
        asa.insert(i)

    asa.insert(add)

    assert asa.delete(delete)
    modified_node = asa.root.children[ch_index]
    assert empty_value == modified_node.keys[0].key

    # check if structure is preserved
    parent = modified_node.parent
    root = asa.root

    assert parent == root
    assert len(parent.keys) == 1

    p_keys = parent.keys
    ch_1, ch_2 = parent.children

    assert ch_1.keys[0].key < p_keys[0].key < ch_2.keys[0].key

    assert ch_1.keys[0].key < ch_2.keys[0].key
    assert len(ch_1.keys) == len(ch_2.keys) == 1
예제 #12
0
def test_asa_delete_should_handle_recursive_rebalancing(
        to_delete, root_keys, insertion_order):
    asa = ASA()
    for i in range(15):
        asa.insert(i)

    assert asa.delete(to_delete)
    assert asa.root.keys == root_keys

    asa_after_delete = ASA()
    for el in insertion_order:
        asa_after_delete.insert(el)

    check_structure(asa.root, asa_after_delete.root)
예제 #13
0
def test_overflow_should_split_tree_building_two_level_tree():
    asa = ASA()

    for i in [5, 10, 2]:
        asa.insert(i)

    assert asa.min == 2
    assert asa.max == 10

    assert not asa.root.leaf
    assert asa.root.keys == [5]

    assert len(asa.root.children) == 2
    assert asa.root.children[0].keys == [2]
    assert asa.root.children[1].keys == [10]

    assert asa.root.children[0].leaf
    assert asa.root.children[1].leaf
예제 #14
0
def test_delete_should_handle_deleting_non_leaf_in_one_level_tree_case(
        elem, node_elem):
    asa = ASA()
    for i in range(3):
        asa.insert(i)

    asa.insert(elem)

    _, node = asa.search(node_elem)

    assert len(node.keys) == 2

    assert asa.delete(1)
    assert elem in asa.root.keys

    elem, node = asa.search(node_elem)
    assert len(node.keys) == 1
예제 #15
0
def test_should_delete_empty_leaf_when_parent_got_two_elements(
        delete_key, parent_key, ch_index):
    asa = ASA()
    for i in range(5):
        asa.insert(i)

    assert asa.delete(delete_key)

    # check if structure is preserved
    values = [i for i in range(5) if i != delete_key]
    asa_values = [el.key for el in asa.sorted_d_queue]

    assert values == asa_values

    _, parent = asa.search(parent_key)

    assert parent == asa.root
    assert len(parent.keys) == 1

    p_keys = parent.keys
    ch_1, ch_2 = parent.children

    assert ch_1.keys[0].key < p_keys[0].key < ch_2.keys[0].key

    assert ch_1.keys[0].key < ch_2.keys[0].key

    child_with_two_keys = parent.children[ch_index]
    assert len(child_with_two_keys.keys) == 2
    assert len(parent.children[int(bool(1 - ch_index))].keys) == 1
예제 #16
0
def test_delete_should_replace_deleted_node_key_with_leaf_key_when_proper_leaf_key_found(
        elem, node_elem):
    asa = ASA()
    for i in range(13):
        asa.insert(i)

    # this will be predecessor or successor of 7
    asa.insert(elem)

    _, node = asa.search(node_elem)

    assert len(node.keys) == 2

    assert asa.delete(7)
    assert elem in asa.root.keys

    elem, node = asa.search(node_elem)
    assert len(node.keys) == 1
예제 #17
0
def test_delete_should_work_for_existing_duplicated_key(
        elements, delete_key, count):
    asa = ASA()
    for key in elements:
        asa.insert(key)

    del_key, _ = asa.search(delete_key)
    assert asa.delete(delete_key)
    assert del_key.count == count
예제 #18
0
def test_delete_sanity_when_deleting_everything_from_builded_key_except_from_one_element(
        del_all_but):
    asa = ASA()
    for i in range(7):
        asa.insert(i)

    delete = [i for i in range(7) if i != del_all_but]

    for dd in delete:
        asa.delete(dd)

    assert len(asa.root.keys) == 1
    assert asa.root.keys == [del_all_but]
    assert asa.root.children == []
예제 #19
0
    def build_from_pandas(self, pd_dataframe):
        columns = pd_dataframe.columns
        for ind, col in enumerate(columns):
            self.attributes[col] = ASA()

            for index, val in enumerate(pd_dataframe[col]):
                inserted = self.attributes[col].insert(val)

                if f'O{index}' not in self.rows:
                    rn = RowNode(f'O{index}')
                    setattr(rn, col, inserted)
                    self.rows[f'O{index}'] = rn
                else:
                    rn = self.rows[f'O{index}']
                    if not hasattr(rn, col):
                        setattr(rn, col, inserted)
                        self.rows[f'O{index}'] = rn

                if not hasattr(inserted, f'O{index}'):
                    setattr(inserted, f'O{index}', self.rows[f'O{index}'])
예제 #20
0
def test_delete_should_remove_key_from_node_with_two_keys_without_rebalancing_v2(
):
    asa = ASA()
    for i in [2, 3, 5, 7, 8, 9, 10, 11]:
        asa.insert(i)

    assert asa.delete(10)

    found, node = asa.search(10)

    assert found is False and node is None

    assert [e.key for e in asa.sorted_d_queue] == [2, 3, 5, 7, 8, 9, 11]

    found, node = asa.search(11)
    assert found

    assert node.parent.keys == [9]
    assert node.leaf is True
예제 #21
0
    def draw_successive_deletion(self,
                                 starting_inserts,
                                 consecutive_deletions,
                                 name='deletion'):
        asa = ASA()
        for el in starting_inserts:
            asa.insert(el)

        save_kwargs = {
            "format": "GIF",
            "save_all": True,
            "duration": 1000,
            "loop": False,
        }

        img = self.draw_asa(asa, save=False)
        evolution = [img]

        deleted = []

        for key in consecutive_deletions:
            asa.delete(key)
            img = self.draw_asa(asa, save=False)
            draw = ImageDraw.Draw(img)
            a_font = ImageFont.truetype(self.font_path, 30)
            draw.text((30, 20),
                      f'Start: {list(starting_inserts)}',
                      fill='black',
                      font=a_font)

            a_font = ImageFont.truetype(self.font_path, 30)
            draw.text((30, 50),
                      f'Deleted: {deleted}',
                      fill='black',
                      font=a_font)

            el_font = ImageFont.truetype(self.font_path, 50)
            draw.text((50, 120), f'Current {key}', fill='red', font=el_font)
            evolution.append(img)
            deleted.append(key)

        evolution[0].save(f'{name}.gif',
                          append_images=evolution[1:],
                          **save_kwargs)
예제 #22
0
def test_should_colapse_structure_when_parent_has_one_hey_and_sibling_also_has_only_one_key(
        delete_key, parent_key):
    asa = ASA()
    for i in range(3):
        asa.insert(i)

    assert asa.delete(delete_key)

    # check if structure is preserved
    values = [i for i in range(3) if i != delete_key]
    asa_values = [el.key for el in asa.sorted_d_queue]

    assert values == asa_values

    _, parent = asa.search(parent_key)

    assert asa.root == parent
    assert len(parent.keys) == 2
    assert parent.children == []
예제 #23
0
def two_level_tree():
    asa = ASA()

    asa.insert(2)
    asa.insert(9)

    asa.insert(1)
    asa.insert(4)
    asa.insert(5)

    asa.insert(3)
    asa.insert(6)
    asa.insert(10)
    return asa
예제 #24
0
def test_asa_search_empty_asa_should_return_node():
    asa = ASA()
    found, _ = asa.search(10)
    assert found is False
예제 #25
0
def test_delete_for_initial_case():
    asa = ASA()

    assert asa.delete(1) is False
예제 #26
0
def test_should_rebalance_when_one_of_sibling_in_three_children_parent_got_two_keys(
        to_add, to_delete, insertion_order):
    asa = ASA()
    for i in range(11):
        asa.insert(i)

    for el in to_add:
        asa.insert(el)

    assert asa.delete(to_delete)

    # integrity check build tree without deleted element
    elements = list(range(7)) + to_add
    elements.remove(to_delete)
    elements.sort()

    asa_after_delete = ASA()
    for el in insertion_order:
        asa_after_delete.insert(el)

    check_structure(asa.root, asa_after_delete.root)
예제 #27
0
def test_should_rebalance_when_one_of_sibling_nodes_for_two_level_tree_with_single_key_root_node(
        to_add, to_delete, insertion_order):
    asa = ASA()
    for i in range(7):
        asa.insert(i)

    for el in to_add:
        asa.insert(el)

    assert asa.delete(to_delete)

    def check_structure(root_1, root_2):
        assert root_1.keys == root_2.keys
        assert len(root_1.children) == len(root_2.children)

        for ch_1, ch_2 in zip(root_1.children, root_2.children):
            check_structure(ch_1, ch_2)

    # integrity check build tree without deleted element
    elements = list(range(7)) + to_add
    elements.remove(to_delete)
    elements.sort()

    asa_after_delete = ASA()
    for el in insertion_order:
        asa_after_delete.insert(el)

    check_structure(asa.root, asa_after_delete.root)
예제 #28
0
def test_delete_should_return_false_if_key_for_delete_not_found():
    asa = ASA()
    for i in [1, 2, 2, 3, 3, 4, 4]:
        asa.insert(i)

    assert asa.delete(10) is False
예제 #29
0
if __name__ == '__main__':
    load_dotenv()

    font_path = os.getenv('FONT_PATH')
    drawer = ASADrawer(font_path, (2800, 700))

    ev = [
        1, 1, 1, 1, 3, 5, 2, 7, 4, 8, 9, 4.5, 4.2, 4.3, 4.4, 10, 11, 4.5, 4.6,
        4.7, 4.8, 6.9, 9.1, 13, 3.2
    ]
    drawer.draw_insertion_evolution(ev)

    deletions = [i for i in range(7) if i != 5]
    drawer.draw_successive_deletion(range(7), deletions)

    asa = ASA()
    asa.insert(1)
    asa.insert(1)
    asa.insert(1)
    asa.insert(1)

    drawer.draw_asa(asa)

    asa.insert(3)
    drawer.draw_asa(asa)

    asa.insert(5)
    drawer.draw_asa(asa)

    asa.insert(2)
    drawer.draw_asa(asa)