Example #1
0
class Stack:
    def __init__(self):
        self.size = 0
        # Why is our DLL a good choice to store our elements?
        # we will be adding and subtracting based on LIFO
        self.storage = DoublyLinkedList()

    def push(self, value):
        # add to the top of the stack, aka the tail
        # increment size by 1
        self.size += 1
        self.storage.add_to_tail(value)

    def pop(self):
        # check if size > 0
        # if true:
        # remove from the top of the stack, aka the tail
        # decrement size by 1
        # else return None
        if self.size > 0:
            self.size -= 1
            return self.storage.remove_from_tail()
        else:
            return None

    def len(self):
        return self.size
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.storage = DoublyLinkedList()
        self.marker = None

    def append(self, item):

        print(f'Marker: {self.marker}')
        # check if there is enough room to store item
        if len(self.storage) < self.capacity:
            self.storage.add_to_tail(item)
            print(f'Buffer Size: {len(self.storage)}/{self.capacity}')

            # set marker marker to first node input to list
            if len(self.storage) == 1:
                self.marker = self.storage.head
        # reached max capacity
        else:
            print(
                f'Overwriting Marker: {self.marker.value} with New Item: {item}'
            )
            # overwrite marker value with input item
            self.marker.value = item
            # change marker to next node if exists
            if self.marker.next:
                self.marker = self.marker.next
            # loops back to the head of list if next is null/reached tail
            else:
                self.marker = self.storage.head
            print(f'Next Marker: {self.marker}')

    def get(self):
        print(self.storage.get_all())
        return self.storage.get_all()
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.storage = DoublyLinkedList()
        self.oldest = None

    def append(self, item):
        if sef.storage.length == 0:
            self.storage.add_to_head(item)
            self.oldest = self.storage.head
            return
        
        elif self.storage.length < self.capacity:
            self.storage.add_to_tail(item)
            
        elif self.storage.length == self.capacity:
            if self.oldest = self.storage.head:
                self.oldest.value = item
                self.oldest = self.oldest.next
                
            elif self.oldest == self.storage.tail:
                self.oldest.value = item
                self.oldest = self.storage.head
                
            else:
                self.oldest.value = item
                self.oldest = self.storage.head
class RingBuffer:
    def __init__(self, capacity):
        '''Because every class needs an "init"'''
        self.capacity = capacity  # It's the capacity
        self.current_node = None  # Gotta start somewhere
        self.storage = DoublyLinkedList()  # Use a DLL to store them in

    def append(self, item):
        if len(self.storage) < self.capacity:  # If there's room in the DLL
            self.storage.add_to_tail(item)  # Insert the newest node at the end
        else:
            if self.current_node == None:  # If cur is empty
                self.storage.head.value = item  # Assign it
                self.current_node = self.storage.head.next  # Update
            else:
                self.current_node.value = item  # Assign it
                self.current_node = self.current_node.next  # Update

    def get(self):
        my_list = []  # Make an empty list for the return
        current_node = self.storage.head  # Get a starting place at the head
        while current_node:
            my_list.append(current_node.value)  # Append
            current_node = current_node.next  # Move on
        return my_list
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.node = None
        self.storage = DoublyLinkedList()  #will be stored in

    def append(self, item):
        if self.storage.length < self.capacity:  #check capacity: if space: add item
            self.storage.add_to_tail(item)  #put item in back
            self.node = self.storage.head  #make mself head
        elif self.storage.length == self.capacity:  #if capacity is full need:
            self.node.value = item  #get the new item
            if self.node == self.storage.tail:  #if at tail
                self.node = self.storage.head  #add to dll head
            else:
                self.node = self.node.next  #move nodes down a spot when adaded

    def get(self):
        storage = []  #list to add nodes to after getting
        node = self.storage.head  #desingate head
        #check for nodes to add, then add nodes to lsit
        # while the exist
        while node is not None:
            storage.append(node.value)
            #get next node, then repeat add
            node = node.next
        #return ist of nodes
        return storage
Example #6
0
class LRUCache:
    """
    Our LRUCache class keeps track of the max number of nodes it
    can hold, the current number of nodes it is holding, a doubly-
    linked list that holds the key-value entries in the correct
    order, as well as a storage dict that provides fast access
    to every node stored in the cache.
    """
    def __init__(self, limit=10):
        self.limit = limit
        self.size = 0
        self.order = DoublyLinkedList()
        # self.order = list()
        self.storage = dict()

    """
    Retrieves the value associated with the given key. Also
    needs to move the key-value pair to the end of the order
    such that the pair is considered most-recently used.
    Returns the value associated with the key or None if the
    key-value pair doesn't exist in the cache.
    """

    def get(self, key):
        if key not in self.storage:
            return None
        else:
            node = self.storage[key]
            self.order.move_to_end(node)
            return node.value[1]

    """
    Adds the given key-value pair to the cache. The newly-
    added pair should be considered the most-recently used
    entry in the cache. If the cache is already at max capacity
    before this entry is added, then the oldest entry in the
    cache needs to be removed to make room. Additionally, in the
    case that the key already exists in the cache, we simply
    want to overwrite the old value associated with the key with
    the newly-specified value.
    """

    def set(self, key, value):
        if key in self.storage:
            node = self.storage[key]
            node.value = (key, value)
            self.order.move_to_end(node)
            return
        if len(self.order) == self.limit:
            evicted = self.order.head.value[0]
            del self.storage[evicted]
            self.order.remove_from_head()
        self.order.add_to_tail((key, value))
        self.storage[key] = self.order.tail
Example #7
0
class Queue:
  def __init__(self):
    self.size = 0
    # using DLL for constant time enqueue and dequeue
    self.dll = DoublyLinkedList()

  def __len__(self):
    return len(self.dll)

  def enqueue(self, item):
    self.dll.add_to_tail(item)
  
  def dequeue(self):
    return self.dll.remove_from_head()

  def len(self):
    return len(self)
Example #8
0
class Queue:
    def __init__(self):
        self.size = 0
        self.storage = DoublyLinkedList()

    def enqueue(self, value):
        self.size += 1
        self.storage.add_to_tail(value)

    def dequeue(self):
        value = self.storage.remove_from_head()

        if value is not None:
            self.size -= 1

        return value

    def len(self):
        return self.size
class TextBuffer:
    def __init__(self, initial_text=None):
        # the contents of our buffer are stored as a linked list
        self.contents = DoublyLinkedList()
        """  
         if we are passed in initial text as an argument
         loop through the string and make linked list nodes
         with every letter 
         """
        if initial_text:
            for char in initial_text:
                self.contents.add_to_tail(char)
        # print the contents of our text buffer

    # O(n)
    def __str__(self):
        s = ""
        """ 
            loop through the linked list
            add each letter to the string
            """
        current = self.contents.head
        while current:
            # concatenate the current letter with the string
            s += current.value
            # move to the next item in the list
            current = current.next
        # __str__ must return a string
        return s

    def append(self, string_to_add):
        """  
        loop through the string
        add each char to the tail
        """
        for char in string_to_add:
            self.contents.add_to_tail(char)

    def prepend(self, string_to_add):
        """ 
        reverse the incoming string
        then loop through it
        and add each char to the head
        """
        for char in string_to_add[::-1]:
            self.contents.add_to_head(char)

    def delete_front(self, chars_to_remove):
        """  
        takes in an argument for how many chars to delete from the front
        """
        for _ in range(chars_to_remove):
            self.contents.remove_from_head()

    def delete_back(self, chars_to_remove):
        """  
        takes in an argument for how many chars to delete from the back
        """
        for _ in range(chars_to_remove):
            self.contents.remove_from_tail()

    """  
    Joins another buffer to itself
    The tail of the current buffer will be the tail of other_buffer
    The head of other_buffer will become the head of this buffer
    """

    def join(self, other_buffer):
        # make sure other_buffer is a TextBuffer
        if not isinstance(other_buffer, TextBuffer):
            print("Join only accepts TextBuffers")
            return
        # set the the current tail to be the tail of the other buffer
        self.contents.tail.next = other_buffer.contents.head
        # set the prev property on other_buffer's head to be the tail
        other_buffer.contents.head.prev = self.contents.tail
        # set the other buffers head to be the current buffer's
        other_buffer.contents.head = self.contents.head
        # set the tail of the current buffer to be other_buffer's tail
        self.contents.tail = other_buffer.contents.tail

    """  
    takes in a string
    creates a new text buffer out of that string
    then calls self.join
    """

    def join_string(self, string_to_join):
        new_buffer = TextBuffer(string_to_join)
        self.join(new_buffer)
Example #10
0
class DoublyLinkedListTests(unittest.TestCase):
    def setUp(self):
        self.node = ListNode(1)
        self.dll = DoublyLinkedList(self.node)

    def test_list_remove_from_tail(self):
        self.dll.remove_from_tail()
        self.assertIsNone(self.dll.head)
        self.assertIsNone(self.dll.tail)
        self.assertEqual(len(self.dll), 0)

        self.dll.add_to_tail(33)
        self.assertEqual(self.dll.head.value, 33)
        self.assertEqual(self.dll.tail.value, 33)
        self.assertEqual(len(self.dll), 1)
        self.assertEqual(self.dll.remove_from_tail(), 33)
        self.assertEqual(len(self.dll), 0)

        self.dll.add_to_tail(68)
        self.assertEqual(len(self.dll), 1)
        self.assertEqual(self.dll.remove_from_tail(), 68)
        self.assertEqual(len(self.dll), 0)

    def test_list_remove_from_head(self):
        self.dll.remove_from_head()
        self.assertIsNone(self.dll.head)
        self.assertIsNone(self.dll.tail)
        self.assertEqual(len(self.dll), 0)

        self.dll.add_to_head(2)
        self.assertEqual(self.dll.head.value, 2)
        self.assertEqual(self.dll.tail.value, 2)
        self.assertEqual(len(self.dll), 1)
        self.assertEqual(self.dll.remove_from_head(), 2)
        self.assertEqual(len(self.dll), 0)

        self.dll.add_to_head(55)
        self.assertEqual(len(self.dll), 1)
        self.assertEqual(self.dll.remove_from_head(), 55)
        self.assertEqual(len(self.dll), 0)

    def test_list_add_to_tail(self):
        self.assertEqual(self.dll.tail.value, 1)
        self.assertEqual(len(self.dll), 1)

        self.dll.add_to_tail(30)
        self.assertEqual(self.dll.tail.prev.value, 1)
        self.assertEqual(self.dll.tail.value, 30)
        self.assertEqual(len(self.dll), 2)

        self.dll.add_to_tail(20)
        self.assertEqual(self.dll.tail.prev.value, 30)
        self.assertEqual(self.dll.tail.value, 20)
        self.assertEqual(len(self.dll), 3)

    def test_node_delete(self):
        node_1 = ListNode(3)
        node_2 = ListNode(4)
        node_3 = ListNode(5)

        node_1.next = node_2
        node_2.next = node_3
        node_2.prev = node_1
        node_3.prev = node_2

        node_2.delete()

        self.assertEqual(node_1.next, node_3)
        self.assertEqual(node_3.prev, node_1)

    def test_node_insert_before(self):
        self.node.insert_before(0)
        self.assertEqual(self.node.prev.value, 0)

    def test_list_add_to_head(self):
        self.assertEqual(self.dll.head.value, 1)

        self.dll.add_to_head(10)
        self.assertEqual(self.dll.head.value, 10)
        self.assertEqual(self.dll.head.next.value, 1)
        self.assertEqual(len(self.dll), 2)

    def test_node_insert_after(self):
        self.node.insert_after(2)
        self.assertEqual(self.node.next.value, 2)

    def test_list_move_to_end(self):
        self.dll.add_to_head(40)
        self.assertEqual(self.dll.tail.value, 1)
        self.assertEqual(self.dll.head.value, 40)

        self.dll.move_to_end(self.dll.head)
        self.assertEqual(self.dll.tail.value, 40)
        self.assertEqual(self.dll.tail.prev.value, 1)
        self.assertEqual(len(self.dll), 2)

        self.dll.add_to_tail(4)
        self.dll.move_to_end(self.dll.head.next)
        self.assertEqual(self.dll.tail.value, 40)
        self.assertEqual(self.dll.tail.prev.value, 4)
        self.assertEqual(len(self.dll), 3)

    def test_list_move_to_front(self):
        self.dll.add_to_tail(3)
        self.assertEqual(self.dll.head.value, 1)
        self.assertEqual(self.dll.tail.value, 3)

        self.dll.move_to_front(self.dll.tail)
        self.assertEqual(self.dll.head.value, 3)
        self.assertEqual(self.dll.head.next.value, 1)
        self.assertEqual(len(self.dll), 2)

        self.dll.add_to_head(29)
        self.dll.move_to_front(self.dll.head.next)
        self.assertEqual(self.dll.head.value, 3)
        self.assertEqual(self.dll.head.next.value, 29)
        self.assertEqual(len(self.dll), 3)

    def test_list_delete(self):
        self.dll.delete(self.node)
        self.assertIsNone(self.dll.head)
        self.assertIsNone(self.dll.tail)
        self.assertEqual(len(self.dll), 0)

        self.dll.add_to_tail(1)
        self.dll.add_to_head(9)
        self.dll.add_to_tail(6)

        self.dll.delete(self.dll.head)
        self.assertEqual(self.dll.head.value, 1)
        self.assertEqual(self.dll.tail.value, 6)
        self.assertEqual(len(self.dll), 2)

        self.dll.delete(self.dll.head)
        self.assertEqual(self.dll.head.value, 6)
        self.assertEqual(self.dll.tail.value, 6)
        self.assertEqual(len(self.dll), 1)

    def test_get_max(self):
        self.assertEqual(self.dll.get_max(), 1)
        self.dll.add_to_tail(100)
        self.assertEqual(self.dll.get_max(), 100)
        self.dll.add_to_tail(55)
        self.assertEqual(self.dll.get_max(), 100)
        self.dll.add_to_tail(101)
        self.assertEqual(self.dll.get_max(), 101)