예제 #1
0
 def test_empty(self):
     l = LinkedList()
     self.assertEquals(True, l.empty())
     l.add_first(1)
     self.assertEquals(False, l.empty())
     l.remove_first()
     self.assertEquals(True, l.empty())
예제 #2
0
 def test_remove_last(self):
     l = LinkedList()
     l.add_first(1)
     l.add_first(2)
     self.assertEquals(1, l.remove_last())
     self.assertEquals(1, len(l))
     self.assertEquals('[2]', str(l))
예제 #3
0
 def test_linked_list(self):
     for test_ob in self.test_cases:
         list = LinkedList()
         for val in test_ob['values']:
             list.add_last(val)
         r_list = LinkedList()
         for val in list:
             r_list.add_first(val)
         i = 0
         for val in list:
             self.assertEqual(val, test_ob['values'][i])
             i += 1
         i = len(test_ob['values']) - 1
         for val in r_list:
             self.assertEqual(val, test_ob['values'][i])
             i -= 1
 def test_linked_list(self):
     for test_ob in self.test_cases:
         list = LinkedList()
         for val in test_ob['values']:
             list.add_last(val)
         r_list = LinkedList()
         for val in list:
             r_list.add_first(val)
         i = 0
         for val in list:
             self.assertEqual(val, test_ob['values'][i])
             i += 1
         i = len(test_ob['values']) - 1
         for val in r_list:
             self.assertEqual(val, test_ob['values'][i])
             i -= 1
예제 #5
0
class LinkedListTestCase(unittest.TestCase):
    def setUp(self):
        self.list = LinkedList()

        self.list.add_first(1)
        self.list.add_first(3)
        self.list.add_first(5)

    def test_is_empty(self):
        tmp_list = LinkedList()
        self.assertTrue(tmp_list.is_empty())

    def test_add_first(self):
        self.assertEqual(3, len(self.list))
        self.assertEqual(5, self.list.get_head().element)
        self.assertEqual(1, self.list.find_tail().element)

    def test_add_last(self):
        tmp_list = LinkedList()
        tmp_list.add_last(1)
        tmp_list.add_last(3)
        tmp_list.add_last(5)

        self.assertEqual(3, len(tmp_list))
        self.assertEqual(1, tmp_list.get_head().element)
        self.assertEqual(5, tmp_list.find_tail().element)

    def test_remove_first(self):
        self.assertEqual(5, self.list.remove_first())
        self.assertEqual(3, self.list.remove_first())
        self.assertEqual(1, self.list.remove_first())

    def test_get(self):
        self.assertEqual(5, self.list.get(0))
        self.assertEqual(3, self.list.get(1))
        self.assertEqual(1, self.list.get(2))

    def test_find_tail(self):
        self.assertEqual(1, self.list.find_tail().element)
        self.list.add_last(9)
        self.assertEqual(9, self.list.find_tail().element)

        tmp_list = LinkedList()
        self.assertTrue(tmp_list.find_tail() is None)
예제 #6
0
class TestLinkedList(unittest.TestCase):
    """Test case used to test methods from LinkedList class"""


    def setUp(self):
        """Test initialization"""
        self.liste = LinkedList()


    def test_newlist_empty(self):
        """2.1 test to check if a new created list is empty"""
        #print(self.liste.empty_list())
        #assertTrue checks if the empty_list() method returns True
        self.assertTrue(self.liste.empty_list())

    def test_add_notempty(self):
        """2.2 test to check that a list is not empty
        if if we've just added an element """
        new_node = Node("x")
        self.liste.add_first(new_node)
        #in this case we check that the list is not empty
        self.assertTrue(not self.liste.empty_list())


    def test_unchanged(self):
        """2.3 test if when we add and remove a new element,
        the linked list remains unchanged"""
        #list creation [a,b]
        node_a, node_b = "a", "b"
        self.liste.add_first(Node(node_a))
        self.liste.add_after(node_a, Node(node_b))
        #store the created list in a variable to be able to compared it later
        first_list = self.liste
        node_d = "d"
        self.liste.add_last(Node(node_d))
        self.liste.remove_node(node_d)
        #assertEqual checks that two given objects are equal
        self.assertEqual(self.liste, first_list)


    def test_add_first(self):
        """2.4 test if an element added at the first position of the list
        is the head of the list"""
        node_e, node_b, node_c = "e", "b", "c"
        self.liste.add_first(Node(node_b))
        self.liste.add_after(node_b, Node(node_c))
        #add the new head node e
        self.liste.add_first(Node(node_e))
        #comparison between the head of the list and the element inserted at the beginning
        self.assertEqual(self.liste.head.__repr__(), node_e)
예제 #7
0
class TestLinkedList(unittest.TestCase):

    """ Class created to proceed tests on the linked list """
    def setUp(self):
        self.new_list = LinkedList()

    def test_new_linked_list_is_empty(self):
        """
        A method to test if the new linked list created is empty or not.
        The head of a new linked list is None!
        """
        self.assertIsNone(self.new_list.head)

    def test_not_empty_after_insertion(self):
        """
        A method to test if after the insertion wether the linked list is empty or not
        """
        self.new_list.add_first(Node(5))
        self.assertIsNotNone(self.new_list)

    def test_unchangement(self):
        """
        A method to test if after an adding and deleting node the linked list is unchanged.
        Original list is created to compare it with the linked list
        after the insertion and the deletion.
        """

        original_list = self.new_list

        self.new_list.add_last(Node(6))
        self.new_list.remove_node(6)
        self.assertEqual(self.new_list, original_list)

    def test_head(self):
        """
        A method to test if after the insertion of a data in the head, then the head == data
        """
        new_head = "i'm the new head!!"
        self.new_list.add_first(Node(new_head))
        self.assertEqual(self.new_list.head.data, new_head)
예제 #8
0
class KthToLastElement_Test(unittest.TestCase):
    def setUp(self):
        self.__linked_list = LinkedList()
        self.__linked_list.add_first(0)
        self.__linked_list.add_first(1)
        self.__linked_list.add_first(2)
        self.__linked_list.add_first(3)
        self.__linked_list.add_first(4)
        self.__linked_list.add_first(5)
        self.__linked_list.add_first(6)
        self.__linked_list.add_first(7)
        self.__linked_list.add_first(8)
        self.__list_head = self.__linked_list.get_head()
        self.__max_value = self.__linked_list.size()

    def testBaseCases(self):
        for i in range(self.__max_value):
            self.assertEqual(kth_to_last_element(self.__list_head, i), i)

    def testErrorCases(self):
        with self.assertRaises(ValueError):
            kth_to_last_element(self.__list_head, -1)
        with self.assertRaises(ValueError):
            kth_to_last_element(self.__list_head, self.__max_value + 1)
예제 #9
0
def select_Menu() -> Menu:
    s = [f'({m.value}){m.name}' for m in Menu]
    while True:
        print(*s, sep = '   ', end='')
        n = int(input(': '))
        if 1 <= n <= len(Menu):
            return Menu(n)

lst = LinkedList() #연결 리스트 생성

while True:
    menu = select_Menu()

    if menu == Menu.머리에노드삽입:
        lst.add_first(int(input('머리 노드에 넣을 값 입력 : ')))

    elif menu == Menu.꼬리에노드삽입:
        lst.add_last(int(input('꼬리 노드에 넣을 값 입력 : ')))

    elif menu == Menu.머리노드삭제:
        lst.remove_first()

    elif menu == Menu.꼬리노드삭제:
        lst.remove_last()

    elif menu == Menu.주목노드출력:
        lst.print_current_node()

    elif menu == Menu.주목노드이동:
        lst.next()
 def test_add_first_length_incremented(self):
     llist = LinkedList()
     node = Node(1)
     llist.add_first(node)
     self.assertEqual(1, llist.length)
second_node = Node('b')
third_node = Node('c')
first_node.next = second_node
second_node.next = third_node
print(llist)

# create the linked list by passing in the nodes list
llist = LinkedList(list('abcde'))
print(llist)

# traversing through the linked list
for e in llist:
    print(e)

# inserting an element to the first of the linked list
llist.add_first(Node('x'))
llist.add_first(Node('y'))
print(llist)

# inserting an element to the last of the linked list
llist.add_last(Node('f'))
llist.add_last(Node('g'))
print(llist)

# inserting a node in between
# adding to an empty linked list
llist = LinkedList()
# llist.add_after('a', Node('b')) # exception
print(llist)
# adding an element after a target node
llist = LinkedList(list('abcde'))
class LinkedListTest(unittest.TestCase):

    def setUp(self):
        self.ll = LinkedList()

    def test_adding_element(self):
        self.ll.add_element(4)
        self.assertEqual(self.ll.size(), 1)

    def test_remove_element(self):
        self.ll.add_element(4)
        size = self.ll.size()
        self.ll.remove(0)
        size2 = self.ll.size()
        self.assertFalse(size == size2)

    def test_len_dunder(self):
        self.assertEqual(0, len(self.ll))

    def test_size(self):
        self.ll = LinkedList(10)
        self.assertEqual(self.ll.size(), 10)

    def test_size_after_adding(self):
        self.ll.add_element(10)
        self.assertEqual(1,self.ll.size())

    def test_size_after_remove(self):
        self.ll.add_element(10)
        self.ll.remove(0)
        self.assertEqual(0, self.ll.size())

    def test_pprint(self):
        self.ll.add_element(10)
        self.ll.add_element(100)
        self.ll.add_element(1000)
        self.assertEqual('[10, 100, 1000]', self.ll.pprint())

    def test_to_list(self):
        self.ll.add_element(100)
        self.ll.add_element(1000)
        self.ll.add_element(100)
        self.ll.add_element(1000)
        self.assertEqual([100, 1000, 100, 1000], self.ll.to_list())

    def test_index(self):
        self.ll.add_element(100)
        self.ll.add_element(1000)
        self.assertEqual(1000, self.ll.index(1).value)

    def test_add_at_index(self):
        self.ll.add_element(100)
        self.ll.add_element(1000)
        self.ll.add_at_index(1, 69)
        self.assertEqual(69, self.ll.index(1).value)

    def test_add_first(self):
        self.ll.add_element(100)
        self.ll.add_first(69)
        self.assertEqual(69, self.ll.index(0).value)

    def test_add_list(self):
        self.ll.add_element(1)
        self.ll.add_list([10, 100, 1000])
        self.assertEqual([1, 10, 100, 1000], self.ll.to_list())

    def test_add_linked_list(self):
        self.ll.add_element(1)
        new_ll = LinkedList()
        new_ll.add_element(10)
        new_ll.add_element(100)
        self.ll.add_linked_list(new_ll)
        self.assertEqual([1, 10, 100], self.ll.to_list())

    def test_ll_from_to(self):
        self.ll.add_element(0)
        self.ll.add_list([1, 10, 100, 1000])
        self.assertEqual([10, 100], self.ll.ll_from_to(2, 3).to_list())

    def test_pop(self):
        self.ll.add_element(1)
        self.ll.add_element(10)
        self.ll.pop()
        self.assertEqual([1], self.ll.to_list())

    def reduce_to_unique(self):
        self.ll.add_element(1)
        self.ll.add_list([10, 100, 10])
        self.assertEqual([1, 10, 100], self.ll.reduce_to_unique())

    def test_set_element(self):
        self.ll.add_element(1)
        self.ll.add_list([10, 100, 1000])
        self.ll.set_element(2, 69)
        self.assertEqual(69, self.ll.index(2).value)
예제 #13
0
def len_recursive(node):
    """
    This function should calculate the length of a linked list recursively
    :param node: the head of the list
    :return: the length of the list
    """
    if node._next == None:
        return 1
    return len_recursive(node._next) + 1


""" main() to do some testing"""
if __name__ == '__main__':
    L1 = LinkedList()
    L2 = LinkedList()
    L1.add_first("Jin")
    L1.add_first("Jun")
    L1.add_first("Jan")
    L1.print()
    L2.add_first(118)
    L2.add_first(115)
    L2.add_first(89)
    L2.add_first(87)
    L2.print()
    find(L1, "Jin")
    find(L1, 908)
    cat(L1, L2)
    L1.print()
    len_l2 = len_recursive(L2._head)
    print("Length of list is: {0}".format(len_l2))
    print("Length of list is: {0}".format(len_recursive(L1._head)))
class LinkedListTest(unittest.TestCase):
    def setUp(self):
        self.ll = LinkedList()

    def test_eq(self):
        ll_2 = LinkedList()
        self.ll.add_element(5)
        self.ll.add_element(6)
        ll_2.add_element(5)
        ll_2.add_element(6)
        self.assertTrue(self.ll == ll_2)

    def test_adding_element(self):
        self.ll.add_element(4)
        self.assertEqual(self.ll.size(), 1)

    def test_remove_element(self):
        self.ll.add_element(4)
        size = self.ll.size()
        self.ll.remove(0)
        size2 = self.ll.size()
        self.assertFalse(size == size2)

    def test_remove_element_2(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.ll.remove(1)
        self.assertEqual(self.ll.index(1), 7)

    def test_size_1(self):
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.assertEqual(self.ll.size(), 3)

    def test_size_2(self):
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.ll.pop()
        self.ll.pop()
        self.assertEqual(self.ll.size(), 1)

    def test_index(self):
        self.ll.add_element(5)
        self.ll.add_element(2)
        self.assertEqual(self.ll.index(0), 5)
        self.assertNotEqual(self.ll.index(1), 5)

    def test_remove_element_2(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.ll.remove(1)
        self.assertEqual(self.ll.index(1), 7)

    def test_pprint(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.pprint(), "5 -> 6 -> 7")

    def test_to_list(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.to_list(), [5, 6, 7])

    def test_add_at_index(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_at_index(1, 7)
        self.assertEqual(self.ll.index(1), 7)
        self.assertEqual(self.ll.index(2), 6)

    def test_add_first(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_first(7)
        self.assertEqual(self.ll.index(0), 7)
        self.assertEqual(self.ll.index(1), 5)

    def test_add_linked_list(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        ll_2 = LinkedList()
        ll_2.add_element(7)
        ll_2.add_element(8)
        self.ll.add_linked_list(ll_2)
        self.assertEqual(self.ll.to_list(), [5, 6, 7, 8])

    def test_ll_from_to(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.ll.add_element(8)
        from_to = self.ll.ll_from_to(1, 3)
        self.assertEqual(from_to.to_list(), [6, 7, 8])

    def test_pop(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.ll.pop()
        size = self.ll.size()
        self.assertEqual(self.ll.index(size - 1), 6)

    def test_reduce_to_unique(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.ll.reduce_to_unique()
        self.assertEqual(self.ll.to_list(), [5, 6, 7])
예제 #15
0
 def test_add_first(self):
     l = LinkedList()
     l.add_first(1)
     l.add_first(2)
     self.assertEquals(2, len(l))
     self.assertEquals("[2,1]", str(l))
예제 #16
0
 def test_iter(self):
     l = LinkedList()
     l.add_first(1)
     l.add_first(2)
     self.assertEquals([2,1], [x for x in l])
예제 #17
0
class LinkedListTest(unittest.TestCase):
    def setUp(self):
        self.ll = LinkedList()

    def test_adding_element(self):
        self.ll.add_element(4)
        self.assertEqual(self.ll.size(), 1)

    def test_remove_element(self):
        self.ll.add_element(4)
        size = self.ll.size()
        self.ll.remove(0)
        size2 = self.ll.size()
        self.assertFalse(size == size2)

    def test_pprint(self):
        self.ll.add_element(4)
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.pprint(), "4->5->6->7")

    def test_to_list(self):
        self.ll.add_element(4)
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.to_list(), [4, 5, 6, 7])

    def test_add_at_index(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.add_at_index(2, 3), 3)

    def test_add_first(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.add_first(5), 5)

    def test_add_linked_list(self):
        ll_two = LinkedList()
        ll_two.add_element(6)
        ll_two.add_element(7)
        ll_two.add_element(8)
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.add_linked_list(ll_two), 8)

    def test_add_list(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        xs = [1, 2, 3]
        self.assertEqual(self.ll.add_list(xs), '5->6->7->1->2->3')

    def test_pop(self):
        self.ll.add_element(5)
        self.ll.add_element(6)
        self.ll.add_element(7)
        self.assertEqual(self.ll.pop(), 7)

    def test_reduce_to_unique(self):
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.ll.add_element(7)
        self.assertEqual(self.ll.reduce_to_unique(), '5->7')

    def test_ll_from_to(self):
        self.ll.add_element(5)
        self.ll.add_element(5)
        self.ll.add_element(7)
        self.assertEqual(self.ll.ll_from_to(1, 2), '5->7')
class TestLinkedList(TestCase):
    def setUp(self):
        self.test_list = LinkedList('head_data')

    def test_set_up(self):
        self.assertIsNone(self.test_list.head.next.data)
        self.assertEqual(self.test_list.head.data, 'head_data')
        self.test_list.head.next = Node(25)
        current_node = self.test_list.head
        self.assertEqual(current_node.next.data, 25)

    def test_get_head(self):
        self.assertEqual(self.test_list.get_head(), self.test_list.head.data)

    def test_add_element(self):
        self.test_list.add_element('node2data')
        self.assertEqual(self.test_list.head.next.data, 'node2data')

    def test_add_at_index(self):
        self.test_list.head.next.data = 'node2data'
        self.test_list.add_at_index(2, 'node3data')
        self.assertEqual(self.test_list.head.next.next.data, 'node3data')

    def test_size(self):
        self.test_list.head.next.data = 'node2data'
        self.test_list.head.next.next = Node('node3data')
        self.assertEqual(self.test_list.size(), 3)

    def test_index(self):
        self.test_list.head.next.data = 'node2data'
        self.assertEqual(self.test_list.index(1), 'node2data')

    def test_remove(self):
        self.test_list.head.next.data = 'node2data'
        self.test_list.head.next.next = Node('node3data')
        self.assertEqual(self.test_list.size(), 3)
        self.test_list.remove(1)
        self.assertEqual(self.test_list.size(), 2)
        self.assertEqual(self.test_list.head.next.data, 'node3data')

    def test_to_list(self):
        self.test_list.head.next.data = 'node2data'
        self.assertEqual(self.test_list.to_list(), ['head_data', 'node2data'])

    def test_add_first(self):
        self.test_list.add_first('add_first_data')
        self.assertEqual(self.test_list.head.next.data, 'head_data')

    def test_add_list(self):
        self.test_list.add_list([1, 2, 3, 4])
        self.assertEqual(self.test_list.size(), 5)

    def test_pop(self):
        self.test_list.head.next.data = 'node2data'
        self.test_list.pop()
        self.assertEqual(self.test_list.size(), 1)

    def test_reduce_to_unique(self):
        self.test_list.head.next.data = 'node2data'
        self.test_list.add_element('node3data')
        self.test_list.add_element('node2data')
        self.test_list.reduce_to_unique()
        self.assertIsNone(self.test_list.head.next.next.next)
예제 #19
0
    """메뉴 선택"""
    s = [f'({m.value}){m.name}' for m in Menu]
    while True:
        print(*s, sep='  ', end='')
        n = int(input(': '))
        if 1 <= n <= len(Menu):
            return Menu(n)


lst = LinkedList()  # 연결 리스트를 생성

while True:
    menu = select_Menu()  # 메뉴 선택

    if menu == Menu.머리에노드삽입:  # 맨 앞에 노드 삽입
        lst.add_first(int(input('머리에 넣을 값을 입력하세요.: ')))

    elif menu == Menu.꼬리에노드삽입:  # 맨 끝에 노드 삽입
        lst.add_last(int(input('꼬리에 넣을 값을 입력하세요.: ')))

    elif menu == Menu.머리노드삭제:  # 맨 앞 노드 삭제
        lst.remove_first()

    elif menu == Menu.꼬리노드삭제:  # 맨 끝 노드 삭제
        lst.remove_last()

    elif menu == Menu.주목노드출력:  # 주목 노드 출력
        lst.print_current_node()

    elif menu == Menu.주목노드이동:  # 주목 노드를 한 칸 뒤로 이동
        lst.next()
class LinkedListTest(unittest.TestCase):
    def setUp(self):
        self.ll = LinkedList()

    def test_adding_element(self):
        self.ll.add_element(4)
        self.assertEqual(self.ll.size(), 1)

    def test_remove_element(self):
        self.ll.add_element(4)
        size = self.ll.size()
        self.ll.remove(0)
        size2 = self.ll.size()
        self.assertFalse(size == size2)

    def test_add_first_element(self):
        self.ll.add_first(30)  #check first el
        self.assertEqual(self.ll.head.value, 30)
        self.ll.add_first(12)  #check tail el after add second el
        self.assertEqual(self.ll.tail.value, 30)

    def test_get_index_of_element(self):
        node = self.ll.get_index(0)  #test empty list
        self.assertEqual(node, None)

        self.ll.add_element(1)  #test index with elements
        self.ll.add_element(2)
        self.ll.add_element(3)
        self.assertEqual(self.ll.get_index(1).value, 2)

    def test_to_list_func(self):
        self.ll.add_element(1)
        self.ll.add_element(4)
        self.ll.add_element(3)
        self.assertEqual(self.ll.to_list(), [1, 4, 3])

    def test_add_at_index(self):
        #invalid indexes
        self.assertFalse(self.ll.add_at_index(1, 3), False)
        self.assertEqual(self.ll.add_at_index(0, 5), None)

    def test_ll_from_to(self):
        self.ll.add_list([1, 2, 3, 4, 5, 6, 7])
        new_ll = self.ll.ll_from_to(3, 6)
        self.assertEqual(new_ll.head.value, 4)
        self.assertEqual(new_ll.tail.value, 7)
        self.assertEqual(new_ll.to_list(), [4, 5, 6, 7])

    def test_pop_func(self):
        # test tail of the list is it pop one el
        self.ll.add_list([1, 2, 3])
        self.ll.pop()
        self.assertEqual(self.ll.tail.value, 2)
        self.ll.pop()
        self.assertEqual(self.ll.tail.value, 1)

    def test_reduce_to_unique(self):
        orig_list = [0, 0, 1, 0, 0, 1, 2, 3, 2]
        expected_list = [0, 1, 2, 3]
        self.ll.add_list(orig_list)
        self.assertEqual(self.ll.to_list(), orig_list)
        unique_ll = self.ll.reduce_to_unique()
        self.assertNotEqual(unique_ll.to_list(), orig_list)
        self.assertEqual(unique_ll.to_list(), expected_list)

    def test_add_to_linked_list(self):
        new_ll = LinkedList()
        new_ll.add_element(1)
        new_ll.add_element(2)
        new_ll.add_element(3)
        self.ll.add_element(0)
        self.ll.add_linked_list(new_ll)
        self.assertEqual(self.ll.head.value, 0)
        self.assertEqual(self.ll.tail.value, 3)
        self.assertEqual(self.ll.to_list(), [0, 1, 2, 3])