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

    def append(self, item):
        if self.storage.__len__() < self.capacity:
            self.storage.add_to_tail(item)
            self.oldest = self.storage.head

        else:
            the_oldest = self.oldest
            if the_oldest.next is not None:
                next_oldest = the_oldest.next
                next_oldest.insert_before(item)
                self.storage.delete(the_oldest)
                self.storage.length = self.capacity
                self.oldest = next_oldest
            else:
                self.storage.remove_from_tail()
                self.storage.add_to_tail(item)
                self.oldest = self.storage.head

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        current_node = self.storage.head
        while current_node is not None:
            list_buffer_contents.append(current_node.value)
            current_node = current_node.next

        return list_buffer_contents
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if not self.current:
            # If self.current is None, the list isn't full yet
            self.storage.add_to_tail(item)
            if self.storage.length == self.capacity:
                # If this puts the list at capacity, set self.current
                # to the head. (self.current is basically the node
                # that will get replaced if a new value is appended.)
                self.current = self.storage.head
        else:
            if self.current is self.storage.head:
                # Replace the head
                self.current = self.storage.head.next
                self.storage.remove_from_head()
                self.storage.add_to_head(item)
            elif self.current is self.storage.tail:
                # Replace the tail
                self.current = self.storage.head
                self.storage.remove_from_tail()
                self.storage.add_to_tail(item)
            else:
                # Log self.current's next and prev, then delete it.
                current_next = self.current.next
                current_prev = self.current.prev
                self.storage.delete(self.current)
                # Set the new self.current
                self.current = current_next
                # Keep track of the tail, since we'll be adding the
                # new value as the tail temporarily.
                tail = self.storage.tail
                self.storage.add_to_tail(item)
                # Set the new node's next and prev to be the same as
                # the old self.current.
                new_node = self.storage.tail
                new_node.next = current_next
                new_node.prev = current_prev
                # Also fix the directions for the nodes that surround the new node
                current_next.prev = new_node
                current_prev.next = new_node
                # Finally, set the tail back to being the proper tail,
                # and make sure it has no "next" node.
                self.storage.tail = tail
                self.storage.tail.next = None

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        node = self.storage.head
        while node:
            list_buffer_contents.append(node.value)
            node = node.next
        return list_buffer_contents
Ejemplo n.º 3
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.max_nodes = limit
        self.num_nodes = 0
        # values in cache_list are key/value dicts
        self.cache_list = DLL()
        # storage holds key, node pairs
        self.storage = {}

    """
    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 in self.storage:
            node = self.storage[key]
            self.cache_list.move_to_front(node)
            return node.value[key]

        else:
            return None

    """
    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 this is an existing key in the storage cache,
        # delete the corresponding node in the list
        if key in self.storage:
            self.cache_list.delete(self.storage[key])
            self.num_nodes -= 1

        self.cache_list.add_to_head({key: value})
        self.storage[key] = self.cache_list.head
        self.num_nodes += 1

        # if cache at max capacity
        if self.num_nodes > self.max_nodes:
            remove_key = list(self.cache_list.tail.value.keys())[0]
            del self.storage[remove_key]
            self.num_nodes -= 1
Ejemplo n.º 4
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.storage = DoublyLinkedList()
        self.cache = {}  # key : node pointer

    """
    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 in self.cache:  #if key exists in cache returns value of node
            node = self.cache[key]
            self.storage.move_to_front(node)
            return node.value[1]
        else:
            return None  #else returns none

    """
    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.cache:  #Checks if key exists in cache and if yes
            node = self.cache[key]  #grabs the node pointer
            self.storage.delete(node)  #removes node from position in DLL
            self.storage.add_to_head((key, value))  #adds node to head
            self.cache[
                key] = self.storage.head  #updates the pointer in cache to head
        elif len(self.cache
                 ) >= self.limit:  #Checks if cache is over limit, if yes
            self.cache.pop(
                self.storage.tail.value[0])  #removes last item from cache
            self.storage.remove_from_tail()  #removed last node from DLL
            self.storage.add_to_head((key, value))  #adds new node to DLL
            self.cache[
                key] = self.storage.head  #adds new item in cache pointing to new node
        else:
            self.size += 1  #updates size
            self.storage.add_to_head((key, value))  #adds new node to DLL
            self.cache[key] = self.storage.head  #adds new pointer to cache
Ejemplo n.º 5
0
class Queue:
    def __init__(self):
        # self.size = 0
        # Why is our DLL a good choice to store our elements?
        self.storage = DoublyLinkedList()
        self.length = 1 if self.storage == 1 else 0
        # self.storage = ?

    def enqueue(self, value):
        # should add an item to the back of the queue
        self.storage.add_to_tail(value)
        self.length += 1
        pass

    def dequeue(self):
        # should remove and return an item from the front of the queue
        if self.length != 0:
            value = self.storage.head.value
            self.storage.delete(self.storage.head)
            self.length -= 1
            return value
        else:
            pass

    def len(self):
        # returns the number of items in the queue
        return self.length
class RingBuffer:
    def __init__(self, capacity):

        self.storage = DoublyLinkedList()
        self.capacity = capacity
        self.current_node = None

    def append(self, item):

        # normal insert
        if len(self.storage) < self.capacity:
            self.storage.add_to_tail(item)
            self.current_node = self.storage.tail

        else:

            if self.current_node == self.storage.tail:
                self.storage.remove_from_head()
                self.storage.add_to_head(item)
                self.current_node = self.storage.head
            else:
                self.storage.insert_after(self.current_node, item)
                self.current_node = self.current_node.next
                self.storage.delete(self.current_node.next)

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        node = self.storage.head
        while node:
            list_buffer_contents.append(node.value)
            node = node.next
        return list_buffer_contents
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if len(self.storage) < self.capacity:
            self.storage.add_to_tail(item)
            self.current = self.storage.tail
        else:
            if self.current == self.storage.tail:
                self.storage.remove_from_head()
                self.storage.add_to_head(item)
                self.current = self.storage.head
            else:
                self.storage.overwrite(self.current, item)
                self.current = self.current.next
                self.storage.delete(self.current.next)

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        cur_node = self.storage.head
        while cur_node:
            list_buffer_contents.append(cur_node.value)
            cur_node = cur_node.next

        return list_buffer_contents
Ejemplo n.º 8
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.cache = DoublyLinkedList()
        self.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 in self.dict:
            value = self.dict[key]
            self.cache.move_to_end({key: value})
            return value
        else:
            return None

    """
    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 self.cache.length == 0:
            self.cache.add_to_head({key: value})
            self.dict[key] = value

        elif key in self.dict:
            self.cache.delete({key: value})
            self.cache.add_to_tail({key: value})
            self.dict[key] = value

        elif self.cache.length < self.limit and not key in self.dict:
            self.cache.add_to_tail({key: value})
            self.dict[key] = value

        elif self.cache.length >= self.limit:
            deleted = self.cache.remove_from_head()
            deleted_key = [*deleted][0]
            del self.dict[deleted_key]
            self.cache.add_to_tail({key: value})
            self.dict[key] = value
Ejemplo n.º 9
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.storage.length == self.capacity:
            # print(self.storage.length == self.capacity)
            # print(self.current['current'].next,' this is the item ', item)
            if self.current['count'] == self.storage.length:
                self.current['current'] = self.storage.head
                self.current['count'] = 0
            if self.current['current'].next:
                new_current = self.current['current'].next
                self.current['current'].insert_after(item)
                self.storage.delete(self.current['current'])
                self.current['current'] = new_current
                self.current['count'] += 1
        self.storage.add_to_tail(item)
        if self.current == None:
            self.current = {"current": self.storage.head, "count": 0}

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []
        node = self.storage.head
        for i in range(self.storage.length):
            if node:
                list_buffer_contents.append(node.value)
                node = node.next

        # TODO: Your code here

        return list_buffer_contents
Ejemplo n.º 10
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.storage.length < self.capacity:
            self.storage.add_to_head(item)
            self.current = self.storage.head
        else:
            if self.current is self.storage.head:
                self.storage.delete(self.storage.tail)
                self.storage.add_to_tail(item)
                self.current = self.storage.tail
            else:
                to_delete = self.current.prev
                self.storage.delete(to_delete)
                self.storage.insert_before(self.current, item)
                self.current = self.current.prev

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []
        i = self.storage.tail
        while i is not None:
            list_buffer_contents.append(i.value)
            i = i.prev
        return list_buffer_contents
Ejemplo n.º 11
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        # 2 cases - capacity - length of dll = capacity and not

        # print("Initial: ", self.get(), " ",
        #       self.storage.length, " Current: ", self.current)

        if self.storage.length == self.capacity:

            node = self.storage.head

            while node.value != self.current:
                node = node.next

            # print("val f: ", node.value)
            # print(self.storage.tail.value)
            # print(node == self.storage.tail)

            if node == self.storage.tail:
                self.storage.remove_from_head()
                self.storage.add_to_head(item)
                self.current = item

            else:
                if node.next == self.storage.tail:
                    self.storage.remove_from_tail()
                    self.storage.add_to_tail(item)

                else:
                    self.storage.delete(node.next)
                    node.insert_after(item)
                    self.storage.length += 1

                self.current = item

            # print("After: ", self.get(), " Current: ", self.current)

        else:
            self.storage.add_to_tail(item)
            self.current = item

            # print("After: ", self.get())

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        node = self.storage.head

        while node:
            list_buffer_contents.append(node.value)
            node = node.next

        return list_buffer_contents
Ejemplo n.º 12
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()
        self.length = 0

    def append(self, item):
        if self.length < self.capacity:
            self.storage.add_to_tail(item)
            self.current = self.storage.tail
            self.length += 1
        elif self.current == self.storage.tail:
            self.storage.remove_from_head()
            self.storage.add_to_head(item)
            self.current = self.storage.head
        else:
            new_node = ListNode(item, self.current, self.current.next)
            self.current.next.prev = new_node
            self.current.next = new_node
            self.storage.delete(new_node.next)
            self.current = new_node
            self.storage.length += 1

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        read_pointer = self.storage.head
        while len(list_buffer_contents) < self.length:
            list_buffer_contents.append(read_pointer.value)
            read_pointer = read_pointer.next

        return list_buffer_contents
Ejemplo n.º 13
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.storage.length < self.capacity:
            self.storage.add_to_tail(item)
        else:
            current_node = None
            node = self.storage.head
            while current_node is None and node is not None:
                if node.value == self.current:
                    current_node = node
                node = node.next
            # Edge case for node at tail
            if current_node is self.storage.tail:
                self.storage.delete(self.storage.head)
                self.storage.add_to_head(item)
            else:
                current_node.insert_after(item)
                self.storage.delete(current_node)
        self.current = item

    def get(self):
        list_buffer_contents = []
        node = self.storage.head
        while node is not None:
            list_buffer_contents.append(node.value)
            node = node.next

        return list_buffer_contents
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.capacity != self.storage.length:
            self.storage.add_to_tail(item)
            self.current = self.storage.tail 
        else:
            if self.current.next:
                self.storage.delete(self.current.next)
                self.current.insert_after(item)
                self.storage.length += 1
                self.current = self.current.next
            else:
                self.current = self.storage.head
                self.storage.delete(self.current)
                self.storage.add_to_head(item)
                self.current = self.storage.head
        
    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []
        current = self.storage.head
        while current:
            list_buffer_contents.append(current.value)
            current = current.next
        return list_buffer_contents
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.current is None:
            self.current = self.storage.head

        if len(self.storage) == self.capacity:
            next_current = self.current.next
            self.current.insert_after(item)
            self.storage.delete(self.current)
            self.current = next_current
            # next_current = self.current.next
            # self.current.delete()
            # self.storage.add_to_head(item)
            # self.current = next_current
        else:
            self.storage.add_to_tail(item)

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        node = self.storage.head
        while node is not None:
            list_buffer_contents.append(node.value)
            node = node.next

        return list_buffer_contents
Ejemplo n.º 16
0
class LRUCache:
    def __init__(self, limit=10):
        self.list = DoublyLinkedList()
        self.dict = {}
        self.limit = limit

    def get(self, key):
        if key in self.dict:
            node = self.dict[key]

            self.list.delete(node)
            self.list.add_to_head(node)
            return node.value
        else:
            return None

    def set(self, key, value):
        if key in self.dict:
            node = self.dict[key]
            node.value = value

            if self.list.head is not node:
                self.list.delete(node)
                self.list.add_to_head(node)
        else:
            new_node = DoublyLinkedList(value)
            if len(self.list) >= self.limit:
                self.dict.pop(list(self.dict.keys())[1])
                self.list.remove_from_tail()
            self.list.add_to_head(new_node)
            self.dict[key] = new_node
Ejemplo n.º 17
0
class Queue:
    def __init__(self):
        self.size = 0
        # Why is our DLL a good choice to store our elements?
        self.storage = DoublyLinkedList()

    # LIFO - Push to tail/add to end
    def enqueue(self, value):
        self.storage.add_to_tail(value)
        self.size += 1

    # Delete head
    def dequeue(self):
        if self.size > 0:
            # Save head node
            head = self.storage.head
            # Delete head
            self.storage.delete(head)
            self.size -= 1
            # Return head value
            return head.value
        else:
            return None

    def len(self):
        return self.size
Ejemplo n.º 18
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.keyStorage = {}
        self.ageStorage = DoublyLinkedList()

    """
    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 self.keyStorage.get(key, None) is None:
            return None
        node = self.keyStorage[key]
        value = node.value
        self.ageStorage.move_to_front(node)
        return value

    """
    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):
        old = self.keyStorage.get(key, None)
        if old:
            self.ageStorage.delete(old)
            self.keyStorage.pop(key, None)

        if len(self.keyStorage) >= self.limit:
            tail = self.ageStorage.tail
            oldKey = tail.key
            self.keyStorage.pop(oldKey, None)
            self.ageStorage.remove_from_tail()

        self.ageStorage.add_to_head(value, key)
        self.keyStorage[key] = self.ageStorage.head

    def __len__(self):
        return len(self.keyStorage)
Ejemplo n.º 19
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.storage = DoublyLinkedList()
        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_dict:  # Check if key exists
            return None
        node = self.storage_dict[key]  # Get key's node
        self.storage.move_to_front(node)  # Move to head
        self.storage_dict[key] = self.storage.head  # Update key
        return self.storage_dict[key].value

    """
    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_dict:  # Delete if exists
            self.storage.delete(self.storage_dict[key])

        self.storage.add_to_head(
            value)  # Add value to head and add to the dict
        self.storage_dict[key] = self.storage.head

        while len(self.storage) > self.limit:  # Cleanup if size > limit
            node = self.storage.tail
            keys = list(self.storage_dict.keys())
            for i in keys:
                if self.storage_dict[i] == node:
                    self.storage_dict.pop(i)
                    break
            self.storage.remove_from_tail()
Ejemplo n.º 20
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.dll = DoublyLinkedList()
        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 in self.storage.keys():
            old_node = self.storage[key]
            new_node = self.dll.move_to_front(old_node)
            self.storage[key] = new_node

            return new_node.value[key]
        else:
            return None

    """
    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.items():
            node = self.storage[key]
            node.value = {key: value}
            return self.dll.move_to_front(node)

        new_node = self.dll.add_to_head({key: value})
        self.storage[key] = new_node

        if len(self.storage) > self.limit:
            node_to_remove = self.dll.tail
            key_to_remove = next(iter(node_to_remove.value))
            self.storage.pop(key_to_remove, None)
            self.dll.delete(node_to_remove)
Ejemplo n.º 21
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.storage = {}
        self.dll = DoublyLinkedList()

    """
    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 self.storage.get(key):
            node = self.storage[key]
            self.dll.move_to_front(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 self.storage.get(key):
            node = self.storage[key]
            node.value = (key, value)
            self.dll.move_to_front(node)
        else:
            node = ListNode((key, value))
            self.dll.add_to_head(node)
            self.storage[node.value[0]] = node
        print(self.storage)
        if len(self.storage) > self.limit:
            node = self.dll.remove_from_tail()
            print(f"In set function: {node}")
            self.storage[node.value[0]] = None
            self.dll.delete(node)
Ejemplo n.º 22
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.storage = DoublyLinkedList()
        self.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 in self.dict:
            node = self.dict[key]
            self.storage.move_to_front(node)
            # Return the value at the 1 index or the actual value as 0 should hold prev value in a doubly linked list
            return node.value[1]
        else:
            return None

    """
    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):
        # check if the key passed already exists, if so delete the stored value to update at the end
        if key in self.dict:
            self.storage.delete(self.dict[key])
        # check if limit has been reached and if so removed oldest node from tail
        elif len(self.storage) >= self.limit:
            node = self.storage.remove_from_tail()
            # delete oldest entry
            del self.dict[node[0]]
        # add this new value to the head of the list and make updated key in dictionary for reference
        self.storage.add_to_head((key, value))
        self.dict[key] = self.storage.head
Ejemplo n.º 23
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.storage = DoublyLinkedList()

    """
  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):
        temp = self.storage.head
        while temp:
            if temp.value[0] == key:
                self.storage.move_to_front(temp)
                return temp.value[1]
            temp = temp.next

    """
  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):
        temp = self.storage.head
        while temp:
            if temp.value[0] == key:
                self.storage.delete(temp)
                temp.value = [key, value]
                self.storage.add_to_head([key, value])
                return True
            temp = temp.next
        if (self.storage.length >= self.limit):
            self.storage.remove_from_tail()
        self.storage.add_to_head([key, value])
        return True
Ejemplo n.º 24
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current_oldest = None
        self.storage = DoublyLinkedList()

    def append(self, item):

        # If we reach the capacity of the buffer set the current pointer back to the beginning
        if self.current_oldest is None:
            self.current_oldest = self.storage.head
        #Is there anything in our list yet? If not add the first item and
        #capacity full case
        if self.storage.length == self.capacity and self.current_oldest == self.storage.head:  #yes?
            self.storage.remove_from_head()
            self.storage.add_to_head(item)
            self.current_oldest = self.current_oldest.next
            # set value
            #move current_oldest
        elif self.storage.length == self.capacity and self.current_oldest == self.storage.tail:
            self.storage.remove_from_tail()
            self.storage.add_to_tail(item)
            self.current_oldest = self.storage.head
            #set value
            #set current oldnest
            #capacity not full case
        #insert item and intialize current oldest value
        elif self.storage.length >= self.capacity:
            self.current_oldest.insert_before(item)
            self.storage.length += 1
            temp = self.current_oldest.next
            self.storage.delete(self.current_oldest)
            self.current_oldest = temp
        else:  #No?
            self.storage.add_to_tail(item)

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        # getting the current value from head
        current = self.storage.head

        # loop till end of list
        while current:
            # add the current value to list
            list_buffer_contents.append(current.value)
            # set up next value
            current = current.next

        return list_buffer_contents
Ejemplo n.º 25
0
class LRUCache:
    def __init__(self, limit: int = 10):
        """
        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.
        """
        self._cache = {}
        self._storage = DoublyLinkedList()
        self._limit = limit

    def get(self, key: str):
        """
        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.
        """

        if key in self._cache:
            self._storage.move_to_front(self._cache[key])
            return self._cache[key].value[1]
        else:
            return None

    def set(self, key: str, value):
        """
        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.
        """

        if key in self._cache:
            self._storage.delete(self._cache[key])
            del self._cache[key]

        if len(self._storage) >= self._limit:
            last = self._storage.tail
            del self._cache[last.value[0]]
            self._storage.delete(last)

        self._storage.add_to_head((key, value))
        self._cache[key] = self._storage.head
Ejemplo n.º 26
0
 def test_delete_non_existing(self):
     list = DoublyLinkedList()
     list.insertLast(1, {"a": 1})
     list.insertLast(2, {"b": 2})
     list.insertAfter(2, 3, {"c": 3})
     self.assertEqual(list.delete(4), None)
     self.assertEqual(len(list.array()), 3)
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.capacity == self.storage.length:
            # if self.current is the tail
            if self.current == self.storage.tail:
                # then remove from head, add item to head,
                self.storage.remove_from_head()
                self.storage.add_to_head(item)
                # and point current to head
                self.current = self.storage.head
            # else insert after current
            else:
                self.current.insert_after(item)
                # change current to currents next
                self.storage.length += 1
                self.current = self.current.next
                # delete what is after the new current
                self.storage.delete(self.current.next)
        # else just add the new item to the tail
        else:
            self.storage.add_to_tail(item)
            # make it the current
            self.current = self.storage.tail

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []
        current = self.storage.head
        # TODO: Your code here
        # if it is only one node
        if self.storage.length == 1:
            # append head.value to the list[]
            list_buffer_contents.append(self.storage.head.value)
        # while next is not pointing to none/while we have not reached the tail
        elif self.storage.length > 1:
            while current.next:
                # append the value of each node to the list
                list_buffer_contents.append(current.value)
                # and move current node ahead one step
                current = current.next
            list_buffer_contents.append(current.value)
        return list_buffer_contents
Ejemplo n.º 28
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        if self.storage.length == 0:
            self.storage.add_to_head(item)
            self.current = self.storage.head
            #nothing in DLL, add item to start
        elif self.storage.length < self.capacity:
            self.storage.add_to_tail(item)
            self.current = self.storage.tail
            #still have room in DLL, add item to list
        elif self.current is self.storage.tail:
            self.storage.remove_from_head()
            self.storage.add_to_head(item)
            self.current = self.storage.head
            # if current is the last item in list
            # remove item from start
            # add this new item to the start
            # now current is the head of the DLL
        else:
            self.current.insert_after(item)
            self.storage.length += 1
            self.current = self.current.next
            self.storage.delete(self.current.next)
            # insert item after current
            # increase length of DLL by 1
            # set current to next
            # deletes the next item to allow new items
            # in DLL as long as not over capacity.

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []
        #empty list
        current = self.storage.head
        #start of DLL  set to variable name current
        while current is not None:
            # as long as current has a value:
            list_buffer_contents.append(current.value)
            #add value of current to end of empty list created
            current = current.next
            #and repeat with each num
        return list_buffer_contents
Ejemplo n.º 29
0
class RingBuffer:
    def __init__(self, capacity):
        self.capacity = capacity
        self.current = None
        self.storage = DoublyLinkedList()

    def append(self, item):
        # if key in self.storage:
        if self.storage.length >= 0 and self.storage.length < self.capacity:
            # node = self.storage[key]
            # node.value = (key, value)
            # self.storage.move_to_end(item)
            self.storage.add_to_tail(item)
            self.current = self.storage.tail
            # return

        # if self.current_num_of_node == self.limit:
        # elif self.storage.length == self.capacity:
        elif self.current == self.storage.tail:
            # del self.storage[self.key_value_entries.head.value[0]]
            # self.key_value_entries.remove_from_head()
            self.storage.remove_from_head()
            self.storage.add_to_head(item)
            self.current = self.storage.head

            # self.current_num_of_node -= 1
        else:
            # self.key_value_entries.add_to_tail((key, value))
            self.current.insert_after(item)
            # self.storage[key] = self.key_value_entries.tail
            # self.current_num_of_node += 1
            self.storage.length += 1
            self.current = self.current.next
            self.storage.delete(self.current.next)

    def get(self):
        # Note:  This is the only [] allowed
        list_buffer_contents = []

        # TODO: Your code here
        current = self.storage.head

        while current != None:
            list_buffer_contents.append(current.value)
            current = current.next

        return list_buffer_contents
Ejemplo n.º 30
0
 def test_delete(self):
     """
     Tests that a Node has been deleted from the list
     """
     dll = DoublyLinkedList()
     dll.add_to_head(1)
     dll.add_to_head(344)
     dll.add_to_head(7)
     node = dll.head
     dll.add_to_head(3)
     dll.delete(node)
     found_val = False
     current_node = dll.head
     while current_node:
         if current_node.value == 7:
             found_val = True
         current_node = current_node.next
     self.assertEqual(found_val, False)
    def testDeletionAndSearch(self):
        dlist = DoublyLinkedList()
        dlist.insert_beginning(10)
        dlist.insert_beginning(11)
        dlist.insert_beginning(16)
        dlist.insert_beginning(13)

        found = dlist.search(11)
        self.assertEqual(found.value, 11)

        dlist.delete(found)

        actual = to_array(dlist)
        expected = [13, 16, 10]
        self.assertEqual(expected, actual)

        found = dlist.search(11)
        self.assertIsNone(found)
Ejemplo n.º 32
0
    def test_doubly_linked_list_delete(self):

        doubly_linked_list = DoublyLinkedList()
        doubly_linked_list.append(25)
        doubly_linked_list.append("Riccardo")
        doubly_linked_list.append("Try")
        doubly_linked_list.insert(6, 3)
        self.assertIsNotNone(doubly_linked_list)
        self.assertTrue(doubly_linked_list.__len__() == 4)
        self.assertTrue(doubly_linked_list.tail.item == 6)
        doubly_linked_list.delete(3)
        self.assertTrue(doubly_linked_list.__len__() == 3)
        self.assertTrue(doubly_linked_list.tail.item == "Try")
        self.assertFalse(doubly_linked_list.tail.item == 6)
        self.assertTrue(doubly_linked_list.head.item == 25)
        self.assertFalse(doubly_linked_list.head.next.item == "Try")
        self.assertTrue(doubly_linked_list.head.next.item == "Riccardo")
        doubly_linked_list.delete(0)
        self.assertTrue(doubly_linked_list.head.item == "Riccardo")
        self.assertTrue(doubly_linked_list.head.next.item == "Try")