Ejemplo n.º 1
0
import sys
sys.path.insert(0, '../')

from ll import LinkedList

ll = LinkedList()
ll.append(20)
ll.prepend(19)
ll.append(21)
print("Is 21 present?", ll.find(21))
print("Is 22 present?", ll.find(22))
print(ll)
print("Deleting", ll.delete(20))
print(ll)
print("Deleting 23", ll.delete(23))
ll.insertAtPos(20, 1)
print("After insertion of 20 at 1", ll)
print("Cycle length", ll.detectCycleLen())
print("Creating a 3-cycle", ll.createcycle(19))
print("Next of 21:", ll.last.next)
print("Cycle length", ll.detectCycleLen())
print("Chain length", ll.findlen())
ll.createcycle(20)
print("Changing to 2-cycle", ll.last, "<->", ll.last.next)
print("Cycle length", ll.detectCycleLen())
print("Chain length", ll.findlen())
print("LL now:", ll)
ll.delete(19)
print("Deleting head", ll)
ll.delete(21)
print("Deleting last", ll)
Ejemplo n.º 2
0
class TestLinkedListMethods(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        n1 = Node(12)
        n2 = Node(55)
        n3 = Node(12)
        n1.next = n2
        n2.next = n3

        self.linked_list = LinkedList()
        self.linked_list.head = n1
        self.linked_list.tail = n3

        super(TestLinkedListMethods, self).__init__(*args, **kwargs)

    def test_add_in_tail(self):
        NODE_VAL = 128
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.tail
        self.assertEqual(node.value, NODE_VAL)

        NODE_VAL = None
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.tail
        self.assertEqual(node.value, NODE_VAL)

        NODE_VAL = 'text'
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.tail
        self.assertEqual(node.value, NODE_VAL)

        NODE_VAL = ['test', 12]
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.tail
        self.assertEqual(node.value, NODE_VAL)

    def test_print_all_nodes(self):
        import io
        from contextlib import redirect_stdout

        f = io.StringIO()
        with redirect_stdout(f):
            self.linked_list.print_all_nodes()

        actual = f.getvalue()
        expected = "12\n55\n12\n"

        self.assertEqual(actual, expected)

    def test_find(self):
        # поиск значения
        NODE_VAL = 12
        node = self.linked_list.find(NODE_VAL)
        self.assertEqual(node.value, NODE_VAL)

        # поиск несуществующего значения
        NODE_VAL = 128
        node = self.linked_list.find(NODE_VAL)
        self.assertIsNone(node)

        # поиск по None
        NODE_VAL = None
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.find(NODE_VAL)
        self.assertEqual(node.value, NODE_VAL)

        # поиск по "сложному" типу данных
        NODE_VAL = ['test', 12]
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.find(NODE_VAL)
        self.assertEqual(node.value, NODE_VAL)

        # поиск по нулевому значению
        NODE_VAL = 0
        self.linked_list.add_in_tail(Node(NODE_VAL))
        node = self.linked_list.find(NODE_VAL)
        self.assertEqual(node.value, NODE_VAL)

        # поиск в пустом списке
        linked_list = LinkedList()
        node = linked_list.find(12)
        self.assertIsNone(node)

        # поиск в списке из одного узла
        linked_list.add_in_tail(Node(12))
        node = linked_list.find(12)
        self.assertEqual(node.value, 12)

        node = linked_list.find(10)
        self.assertIsNone(node)

    def test_find_all(self):
        # поиск значения
        NODE_VAL = 12
        nodes = self.linked_list.find_all(NODE_VAL)
        self.assertEqual(len(nodes), 2)
        for node in nodes:
            self.assertEqual(node.value, NODE_VAL)

        # поиск по "сложному" типу данных
        NODE_VAL = ['test', 12]
        self.linked_list.add_in_tail(Node(NODE_VAL))
        nodes = self.linked_list.find_all(NODE_VAL)
        self.assertEqual(len(nodes), 1)
        for node in nodes:
            self.assertEqual(node.value, NODE_VAL)

        # поиск несуществующего значения
        NODE_VAL = 120
        nodes = self.linked_list.find_all(NODE_VAL)
        self.assertEqual(len(nodes), 0)

        # получение всех узлов списка
        nodes = self.linked_list.find_all()
        self.assertEqual(len(nodes), 4)

        # поиск по None
        NODE_VAL = None
        nodes = self.linked_list.find_all(NODE_VAL)
        self.assertEqual(len(nodes), 4)

        # поиск по нулевому значению
        NODE_VAL = 0
        self.linked_list.add_in_tail(Node(NODE_VAL))
        nodes = self.linked_list.find_all(NODE_VAL)
        self.assertEqual(len(nodes), 1)

        # поиск в пустом списке
        linked_list = LinkedList()
        nodes = linked_list.find_all(12)
        self.assertEqual(len(nodes), 0)

        # поиск в списке из одного узла
        linked_list.add_in_tail(Node(12))
        nodes = linked_list.find_all(12)
        self.assertEqual(len(nodes), 1)
        for node in nodes:
            self.assertEqual(node.value, 12)

        nodes = linked_list.find_all(10)
        self.assertEqual(len(nodes), 0)

    def test_delete(self):
        # удаление первого найденого элемента из нескольких найденных
        NODE_VALUE = 12
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 2)

        self.linked_list.delete(NODE_VALUE)
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 1)
        self.assertEqual(self.linked_list.head.value, 55)
        self.assertEqual(self.linked_list.tail.value, 12)

        # удаление всех найденных элементов
        self.linked_list.add_in_tail(Node(NODE_VALUE))
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 2)

        self.linked_list.delete(NODE_VALUE, True)
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 0)
        self.assertEqual(self.linked_list.tail.value, 55)

        # удаление единственного элемента в списке
        self.linked_list.delete(55)
        self.assertEqual(self.linked_list.len(), 0)
        self.assertIsNone(self.linked_list.head)
        self.assertIsNone(self.linked_list.tail)

        # удаление элемента из пустого списка
        self.assertEqual(self.linked_list.len(), 0)
        self.linked_list.delete(55)
        self.assertEqual(self.linked_list.len(), 0)
        self.assertIsNone(self.linked_list.head)
        self.assertIsNone(self.linked_list.tail)

        # удаление элемента из списка после чего остается только один элемент в списке
        self.linked_list.add_in_tail(Node(NODE_VALUE))
        self.linked_list.add_in_tail(Node(55))

        self.linked_list.delete(55)
        self.assertEqual(self.linked_list.head.value, 12)
        self.assertEqual(self.linked_list.tail.value, 12)
        self.assertIsNone(self.linked_list.head.next)
        self.assertIsNone(self.linked_list.tail.next)
        self.assertEqual(self.linked_list.len(), 1)

        self.linked_list.add_in_tail(Node(55))

        self.linked_list.delete(NODE_VALUE)
        self.assertEqual(self.linked_list.head.value, 55)
        self.assertEqual(self.linked_list.tail.value, 55)
        self.assertIsNone(self.linked_list.head.next)
        self.assertIsNone(self.linked_list.tail.next)
        self.assertEqual(self.linked_list.len(), 1)

        # проверка на удаление элементов со значением 0 и проверка связей для всех узлов в памяти
        n1 = Node(0)
        n2 = Node(0)
        n3 = Node(1)
        n4 = Node(1)
        n5 = Node(2)
        n6 = Node(2)
        linked_list = LinkedList()
        linked_list.add_in_tail(n1)
        linked_list.add_in_tail(n2)
        linked_list.add_in_tail(n3)
        linked_list.add_in_tail(n4)
        linked_list.add_in_tail(n5)
        linked_list.add_in_tail(n6)
        linked_list.delete(1, True)
        linked_list.delete(2, True)
        linked_list.delete(0)
        self.assertEqual(linked_list.head.value, 0)
        self.assertEqual(linked_list.tail.value, 0)
        self.assertIsNone(linked_list.head.next)
        self.assertIsNone(linked_list.tail.next)
        self.assertEqual(linked_list.len(), 1)

        self.assertIsNone(n1.next)
        self.assertIsNone(n2.next)
        self.assertIsNone(n3.next)
        self.assertIsNone(n4.next)
        self.assertIsNone(n5.next)
        self.assertIsNone(n6.next)

    def test_len(self):
        count_nodes = self.linked_list.len()
        self.assertEqual(count_nodes, 3)

        NODE_VALUE = 12
        self.linked_list.delete(NODE_VALUE, True)
        count_nodes = self.linked_list.len()
        self.assertEqual(count_nodes, 1)

    def test_clean(self):
        self.linked_list.clean()
        self.assertIsNone(self.linked_list.head)
        self.assertIsNone(self.linked_list.tail)
        self.assertEqual(self.linked_list.len(), 0)

    def test_insert(self):
        # вставка в список со многими элементами в начало списка
        self.linked_list.insert(None, Node(1200))
        self.assertEqual(self.linked_list.head.value, 1200)
        self.assertEqual(self.linked_list.head.next.value, 12)
        self.assertEqual(self.linked_list.len(), 4)
        self.assertEqual(self.linked_list.tail.value, 12)

        # вставка в список со многими элементами в конец списка
        linked_list = LinkedList()
        linked_list.add_in_tail(Node(1))
        linked_list.add_in_tail(Node(2))
        linked_list.add_in_tail(Node(3))

        linked_list.insert(linked_list.tail, Node(1200))
        self.assertEqual(linked_list.head.value, 1)
        self.assertEqual(linked_list.head.next.value, 2)
        self.assertEqual(linked_list.len(), 4)
        self.assertEqual(linked_list.tail.value, 1200)

        # вставка в список со многими элементами
        node = self.linked_list.find(55)
        self.linked_list.insert(node, Node(66))
        self.assertEqual(node.next.value, 66)
        self.assertEqual(self.linked_list.len(), 5)
        self.assertEqual(self.linked_list.head.value, 1200)
        self.assertEqual(self.linked_list.tail.value, 12)

        # вставка в список отличного от типа Node элемента
        NODE_VALUE = 100
        self.linked_list.insert(node, NODE_VALUE)
        self.assertEqual(self.linked_list.len(), 5)
        self.assertEqual(self.linked_list.head.value, 1200)
        self.assertEqual(self.linked_list.tail.value, 12)

        # вставка в список после несуществующего элемента
        linked_list = LinkedList()
        NODE_VALUE = 100
        linked_list.add_in_tail(Node(1))
        linked_list.add_in_tail(Node(2))
        linked_list.add_in_tail(Node(3))
        linked_list.insert(Node(1500), Node(NODE_VALUE))
        self.assertEqual(linked_list.len(), 3)
        self.assertEqual(linked_list.head.value, 1)
        self.assertEqual(linked_list.tail.value, 3)

        # вставка в пустой список
        linked_list = LinkedList()
        linked_list.insert(None, Node(NODE_VALUE))
        node = linked_list.find(NODE_VALUE)
        self.assertEqual(linked_list.len(), 1)
        self.assertEqual(node.value, NODE_VALUE)
        self.assertEqual(node.next, None)
        self.assertEqual(linked_list.head.value, NODE_VALUE)
        self.assertEqual(linked_list.tail.value, NODE_VALUE)

        # вставка в пустой список после несуществующего элемента
        linked_list = LinkedList()
        linked_list.insert(Node(10), Node(10))
        self.assertEqual(linked_list.len(), 0)
        self.assertIsNone(linked_list.head)
        self.assertIsNone(linked_list.tail)

        # вставка в список в начало с одним элементом и проверка на нулевое значение
        linked_list = LinkedList()
        linked_list.add_in_tail(Node(1))
        linked_list.insert(None, Node(0))
        node = linked_list.find(0)
        self.assertEqual(linked_list.len(), 2)
        self.assertEqual(node.value, 0)
        self.assertEqual(node.next.value, 1)
        self.assertEqual(linked_list.head.value, 0)
        self.assertEqual(linked_list.tail.value, 1)

        # вставка в список с одним элементом в конец списка
        linked_list = LinkedList()
        linked_list.add_in_tail(Node(1))
        node = linked_list.find(1)
        linked_list.insert(node, Node(0))
        node = linked_list.find(0)
        self.assertEqual(linked_list.len(), 2)
        self.assertEqual(node.value, 0)
        self.assertIsNone(node.next)
        self.assertEqual(linked_list.head.value, 1)
        self.assertEqual(linked_list.tail.value, 0)

    def test_validate_node(self):
        self.assertTrue(self.linked_list._validate_node(Node(123)))
        self.assertFalse(self.linked_list._validate_node(123))
        self.assertFalse(self.linked_list._validate_node('test'))
Ejemplo n.º 3
0
class Channel:
    """
    This class provides Go like implementation for channels except for the operators used.
    Much like Go channels, the calls over channels are blocking meaning, sending and receiving over a channel
    is blocked until a condition is met.

    There are 3 methods exposed publicly:
        1. Send - sends a message over the channel
        2. Receive - receives a message from the channel
        3. Close - closes the channel

    Channels can also be iterated over using a for loop.
    """

    __MAX_WAIT_TIME = 30.0

    def __init__(self, _type, size=-1):
        """ initializing for channels"""
        self.__buffer = LinkedList()
        self.__capacity = size
        self.__closed = False
        self.__cond = Condition()
        self.__type = _type
        self.__zero_value_map = {
            int: 0,
            float: 0.0,
            str: '',
            tuple: (),
            list: [],
            dict: {},
            set: set()
        }

    @property
    def capacity(self):
        return self.__capacity

    def __len__(self):
        """
        Calculates the number of messages in the channel
        :return number of messages in the channel
        """
        with self.__cond:
            return self.__buffer.size

    def __is_empty(self):
        """
        checks whether a channel is empty
        :return True if a channel is empty, False otherwise
        """
        return len(self) == 0

    def __is_full(self):
        """
        checks whether a channel is full. A channel with size -1 is never full.
        :return True if a channel is full, False otherwise """
        with self.__cond:
            return self.__buffer.size == self.__capacity

    def __flushed_buffer(self):
        """
        Checks whether the channel has been closed and emptied.
        :returns True if the channel has been closed and emptied, false otherwise
        """
        with self.__cond:
            return self.__closed and self.__buffer.head is None

    def __zero_value(self):
        """
        Calculates the zero value of the type of the channel.
        Zero Values are values or expressions of a particular type which evaluate to False as a boolean.
        Zero values for default python types are stored in a dictionary
        :return: zero value of the default python types, None for other types
        """
        try:
            return self.__zero_value_map[self.__type]
        except KeyError:
            return None

    def __iter__(self):
        """
        Iterate over the channel and depopulate it. Exits when the buffer has been flushed
        :returns each message in the buffer. """
        while not self.__flushed_buffer():
            message, ok = self.__depopulate()
            if not ok:
                return
            yield message

    def __check_type(self, _input):
        """
        Ensure type check for channels.
        :param _input: input to be checked
        :raises TypeMismatchException if input object is not an instance of type defined during initialization of the
        channel
        """
        if not isinstance(_input, self.__type):
            raise TypeMismatchException(
                "Input Type does not match the type of channel")

    def __wait(self):
        """
        Waits for a specified amount of time. This is necessary when waiting for a thread to finish sending or receiving
        over the channel
        """
        with self.__cond:
            self.__cond.wait(self.__class__.__MAX_WAIT_TIME)

    def __is_closed(self):
        """
        Checks whether a channel closed
        :return True a channel is closed, False otherwise
        """
        with self.__cond:
            return self.__closed

    def __populate(self, message):
        """
        Populates the channel with an message. If channel is at capacity, waits till channel is
        depopulated at least once. Also notifies all threads waiting to receive on the other end of the channel
        :param message: message to be added to the buffer
        """
        self.__check_type(message)
        if self.__capacity != -1 and self.__is_full():
            while not self.__is_closed() and self.__is_full():
                self.__wait()
            if self.__is_closed():
                return
        with self.__cond:
            self.__buffer.insert(message)
            self.__cond.notifyAll()

    def __depopulate(self):
        """
        Depopulates the channel and returns the message. If channel is empty, waits till channel is
        populated at least once. If the channel is closed before depopulating, a special object is returned.
        Also notifies all threads waiting to send on the other end of the channel.
        :return tuple of (message, True) if channel is open, tuple of (None, False) otherwise
        """
        while not self.__is_closed() and self.__is_empty():
            self.__wait()
        if self.__flushed_buffer():
            return None, False
        with self.__cond:
            message = self.__buffer.delete()
            self.__cond.notifyAll()
            return message, True

    def send(self, message):
        """
        Sends a message across the channel. Raises an exception if it is called on a closed channel
        :param message: message to be sent on the channel
        :raises ChannelClosedException if send is called on a closed channel
        """
        if self.__is_closed():
            raise ChannelClosedException(
                "Invalid operation send on closed channel")
        self.__populate(message)

    def receive(self):
        """
        Receives a message from the channel
        :returns a message from the buffer
        """
        message, ok = self.__depopulate()
        if not ok:
            return self.__zero_value(), False
        return message, True

    def close(self):
        """
        Closes the channel.
        :raises ChannelClosedException if it is called on a closed channel
        """
        with self.__cond:
            if self.__closed:
                raise ChannelClosedException("Cannot close a closed channel")
            self.__closed = True
            self.__cond.notifyAll()
Ejemplo n.º 4
0
    def test_delete(self):
        # удаление первого найденого элемента из нескольких найденных
        NODE_VALUE = 12
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 2)

        self.linked_list.delete(NODE_VALUE)
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 1)
        self.assertEqual(self.linked_list.head.value, 55)
        self.assertEqual(self.linked_list.tail.value, 12)

        # удаление всех найденных элементов
        self.linked_list.add_in_tail(Node(NODE_VALUE))
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 2)

        self.linked_list.delete(NODE_VALUE, True)
        nodes = self.linked_list.find_all(NODE_VALUE)
        self.assertEqual(len(nodes), 0)
        self.assertEqual(self.linked_list.tail.value, 55)

        # удаление единственного элемента в списке
        self.linked_list.delete(55)
        self.assertEqual(self.linked_list.len(), 0)
        self.assertIsNone(self.linked_list.head)
        self.assertIsNone(self.linked_list.tail)

        # удаление элемента из пустого списка
        self.assertEqual(self.linked_list.len(), 0)
        self.linked_list.delete(55)
        self.assertEqual(self.linked_list.len(), 0)
        self.assertIsNone(self.linked_list.head)
        self.assertIsNone(self.linked_list.tail)

        # удаление элемента из списка после чего остается только один элемент в списке
        self.linked_list.add_in_tail(Node(NODE_VALUE))
        self.linked_list.add_in_tail(Node(55))

        self.linked_list.delete(55)
        self.assertEqual(self.linked_list.head.value, 12)
        self.assertEqual(self.linked_list.tail.value, 12)
        self.assertIsNone(self.linked_list.head.next)
        self.assertIsNone(self.linked_list.tail.next)
        self.assertEqual(self.linked_list.len(), 1)

        self.linked_list.add_in_tail(Node(55))

        self.linked_list.delete(NODE_VALUE)
        self.assertEqual(self.linked_list.head.value, 55)
        self.assertEqual(self.linked_list.tail.value, 55)
        self.assertIsNone(self.linked_list.head.next)
        self.assertIsNone(self.linked_list.tail.next)
        self.assertEqual(self.linked_list.len(), 1)

        # проверка на удаление элементов со значением 0 и проверка связей для всех узлов в памяти
        n1 = Node(0)
        n2 = Node(0)
        n3 = Node(1)
        n4 = Node(1)
        n5 = Node(2)
        n6 = Node(2)
        linked_list = LinkedList()
        linked_list.add_in_tail(n1)
        linked_list.add_in_tail(n2)
        linked_list.add_in_tail(n3)
        linked_list.add_in_tail(n4)
        linked_list.add_in_tail(n5)
        linked_list.add_in_tail(n6)
        linked_list.delete(1, True)
        linked_list.delete(2, True)
        linked_list.delete(0)
        self.assertEqual(linked_list.head.value, 0)
        self.assertEqual(linked_list.tail.value, 0)
        self.assertIsNone(linked_list.head.next)
        self.assertIsNone(linked_list.tail.next)
        self.assertEqual(linked_list.len(), 1)

        self.assertIsNone(n1.next)
        self.assertIsNone(n2.next)
        self.assertIsNone(n3.next)
        self.assertIsNone(n4.next)
        self.assertIsNone(n5.next)
        self.assertIsNone(n6.next)