Ejemplo n.º 1
0
class FavoritesList:
    class _Item:
        __slots__ = '_value', '_count'

        def __init__(self, e):
            self._value = e
            self._count = 0

    def __init__(self):
        self._data = PositionalList()

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

    def is_empty(self):
        return len(self._data) == 0

    def access(self, e):
        p = self._find_position(e)
        if p is None:
            p = self._data.add_last(self._Item(e))
        p.element()._count += 1
        self._move_up(p)

    def remove(self, e):
        p = self._find_position(e)
        if p is not None:
            self._data.delete(p)

    def top(self, k=1):
        if not 1 <= k <= len(self):
            raise ValueError('Illegal value for k')

        walk = self._data.first()
        for j in range(k):
            item = walk.element()
            yield item._value
            walk = self._data.after(walk)

    def _find_position(self, e):
        walk = self._data.first()
        while walk is not None and walk.element()._value != e:
            walk = self._data.after(walk)
        return walk

    def _move_up(self, p):
        if p == self._data.first():
            return

        cnt = p.element()._count
        walk = self._data.before(p)
        if cnt <= walk.element()._count:
            return

        while (walk != self._data.first()
               and cnt > self._data.before(walk).element()._count):
            walk = self._data.before(walk)

        self._data.add_before(walk, self._data.delete(p))
Ejemplo n.º 2
0
 def top(self, k):
     if not 1 <= k <= len(self):
         raise ValueError('Illegal value for k')
     temp = PositionalList()
     for item in self._data:
         temp.add_last(item)
     for j in range(k):
         highPos = temp.first()
         walk = temp.after(highPos)
         while walk is not None:
             if walk.element()._count > highPos.element()._count:
                 highPos = walk
         yield highPos.element()._value
         temp.delete(highPos)
Ejemplo n.º 3
0
class SortedPriorityQueue(PriorityQueueBase):
    def __init__(self):
        self._data = PositionalList()

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

    def add(self, key, value):
        newest = self._Item(key, value)
        walk = self._data.last()
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)
        else:
            self._data.add_after(walk, newest)

    def min(self):
        if self.is_empty():
            raise Empty('Priority queue is empty')
        p = self._data.first()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        if self.is_empty():
            raise Empty('Priority queue is empty')
        item = self._data.delete(self._data.first())
        return (item._key, item._value)
Ejemplo n.º 4
0
class SortedPriorityQueue(PriorityQueueBase):
    """
    A priority queue class storing elements sorted according to priority
    """
    def __init__(self):
        self._data = PositionalList()

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

    def min(self):
        if self.is_empty():
            raise EmptyException('Priority queue is empty.')
        p = self._data.first()
        return (p.element()._key, p.element()._value)

    def remove_min(self):
        if self.is_empty():
            raise EmptyException('Priority queue is empty.')
        p = self._data.first()
        item = self._data.delete(p)
        return (item._key, item._value)

    def add(self, k, v):
        newest = self._Item(k, v)
        walk = self._data.last()
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)
        else:
            self._data.add_after(walk, newest)
class SortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """ A min-oriented priority queue implemented with a sorted list. """
    def __init__(self):
        """ Create a new empty Priority Queue. """
        self._data = PositionalList()

    def __len__(self):
        """ Return the num of items in the priority queue. """
        return len(self._data)

    def add(self, key, value):
        """ Add a key-value pair. """
        newest = self._Item(key, value)  # make new item instance
        walk = self._data.last()  # walk backward looking for smaller key
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)  # new key is smallest
        else:
            self._data.add_after(walk, newest)  # newest goes after walk

    def min(self):
        """ Return but do not remove (k,v) tuple with min key """
        if self.is_empty():
            raise Exception('Priority queue is empty.')
        p = self._data.first()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        """ Remove and return (k,v) tuple with min key. """
        if self.is_empty():
            raise Exception('Priority queue is empty.')
        item = self._data.delete(self._data.first())
        return (item._key, item._value)
Ejemplo n.º 6
0
class UnsortedPriorityQueue(PriorityQueueBase):
    def _find_min(self):
        if self.is_empty():
            raise Empty('Priority queue is empty')
        small = self._data.first()
        walk = self._data.after(small)
        while walk is not None:
            if walk.element() < small.element():
                small = walk
            walk = self._data.after(walk)
        return small

    def __init__(self):
        self._data = PositionalList()

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

    def add(self, key, value):
        self._data.add_last(self._Item(key, value))

    def min(self):
        p = self._find_min()
        item = p.element()
        return(item._key, item._value)

    def remove_min(self):
        p = self._find_min()
        item = self._data.delete(p)
        return (item._key, item._value)
Ejemplo n.º 7
0
class UnsortedPriorityQueue(PriorityQueueBase):

    def __init__(self):
        self._data = PositionalList()

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

    def _find_min(self):
        if self.is_empty():
            raise Empty('Priority queue is empty.')
        min = self._data.first()
        walk = self._data.after(min)
        while walk is not None:
            if walk.element() < min.element():
                min = walk
            walk = self._data.after(min)
        return min

    def add(self, key, value):
        self._data.add_last(self._Item(key, value))

    def min(self):
        p = self._find_min()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        p = self._find_min()
        item = self._data.delete(p)
        return item._key, item._value
Ejemplo n.º 8
0
class UnsortedPriorityQueue(PriorityQueueBase):
    """
    A priority queue class storing elements in arbitrary order
    """
    def __init__(self):
        self._data = PositionalList()

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

    def _find_min(self):
        if self.is_empty():
            raise EmptyException("Priority Queue is empty.")
        curr_min = self._data.first()
        walk = self._data.after(curr_min)
        while walk is not None:
            if walk.element() < curr_min.element():
                curr_min = walk
            walk = self._data.after(walk)
        return curr_min

    def min(self):
        p = self._find_min()
        return (p.element()._key, p.element()._value)

    def remove_min(self):
        p = self._find_min()
        item = self._data.delete(p)
        return (item._key, item._value)

    def add(self, k, v):
        self._data.add_last(self._Item(k, v))
Ejemplo n.º 9
0
class UnsortedPriorityQueue(PriorityQueueBase):
    """ a min-oriented priority queue implemented with an unsorted list """

    def __init__(self):
        """ Create a new empty Priority Queue """
        self._data = PositionalList()

    def _find_min(self):            # nonpublic utility
        """ Return Position of item with min key """
        if self.is_empty():         # method inherited from base class
            raise Exception('Priority queue is empty')
        small = self._data.first()
        walk = self._data.after(small)

    def __len__(self):
        """ Return the number of items in the priority queue. """
        return len(self._data)

    def add(self, key, value):
        """ add a key-value pair. """
        self._data.add_last(self._Item(key, value))

    def min(self):
        """ Return but do not remove (k,v) tuple with min key. """
        p = self._find_min()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        """ Remove and return (k,v) tuple with min key. """
        p = self._find_min()
        item = self._data.delete(p)
        return (item._key, item._value)
Ejemplo n.º 10
0
class SortedPriorityQueue(PriorityQueueBase):

    def __init__(self):
        self._data = PositionalList()

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

    def add(self, key, value):
        new = self._Item(key, value)
        walk = self._data.last()
        while walk is not None and new < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(new)
        else:
            self._data.add_before(walk, new)

    def min(self):
        if self.is_empty():
            raise Empty('Priority queue is empty.')
        p = self._data.first()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        if self.is_empty():
            raise Empty('Priority queue is empty.')
        item = self._data.delete(self._data.first())
        return item._key, item._value
Ejemplo n.º 11
0
class sortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with an unsorted list."""

    #----------------------------- nonpublic behavior -----------------------------

    #------------------------------ public behaviors ------------------------------
    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)
        walk = self._data.last()
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)
        else:
            self._data.add_after(walk, newest)

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
        if self.is_empty():
            raise Exception("Priority queue is empty")
        p = self._data.first()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
        if self.is_empty():
            raise Exception("Priority Queue is empty.")
        item = self._data.delete(self._data.first())
        return (item._key)

    def __iter__(self):
        """Generate iteration of the map's keys."""
        for item in self._data:
            yield item  # yield the KEY

    def insertionSort(self, A):
        for i in A:
            self.add(i, i)
        for i in range(len(A)):
            A[i] = self.remove_min()
class UnsortedPriorityQueue(PriorityQueue):
    """
    An implementstion of a PriorityQueue
    Store items in an unsorted list
    Requires searching the entire list when accessing items
    """
    def __init__(self):
        """
        Creates an empty PriorityQueue
        """
        self._data = PositionalList()

    def __len__(self):
        """
        returns: the number of items in the PriorityQueue
        """
        return len(self._data)

    def add(self, key, value):
        """
        Adds a key-value pair to the PriorityQueue
        """
        self._data.add_last(self._Item(key, value))

    def _find_min(self):
        """
        Non-public utility method
        returns: the item with the minimum key
        """
        if self.is_empty():
            raise Empty('Priority Queue is empty')
        minimum = self._data.first()
        walk = self._data.after(minimum)
        while walk is not None:
            if walk.element() < minimum.element(
            ):  # __lt__ is implemented by the PriorityQueue class
                minimum = walk
            walk = self._data.after(walk)
        return minimum

    def min(self):
        """
        returns: the (k,v) tuple with the minimum key, without removing it
        """
        p = self._find_min()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        """
        removes the minimum (k,v) tuple from the priority queue
        returns: the (k,v) tuple
        """
        p = self._find_min()
        item = self._data.delete(p)  # PositionalList removes and returns item
        return (item._key, item._value)
 def top(self, k):
     """Generate sequence of top k elements in terms of access count."""
     if not 1 <= k <= len(self):
         raise ValueError('Illegal value for k')
     # we begin by making a copy of the original list
     temp = PositionalList()
     for item in self._data:  # positional lists support iteration
         temp.add_last(item)
     # we repeatedly find, report, and remove element with largest count
     for j in range(k):
         # find and report next highest from temp
         highPos = temp.first()
         walk = temp.after(highPos)
         while walk is not None:
             if walk.element()._count > highPos.element()._count:
                 highPos = walk
             walk = temp.after(walk)
         # we have found the element with highest count
         yield highPos.element()._value  # report element to user
         temp.delete(highPos)  # remove from temp list
Ejemplo n.º 14
0
class PositionalQueue(object):
    """ A queue implementation based on positional list.

    With enqueue returning a position instance and support for a new method,
    delete(p), that removes the element associated with position p from the
    queue.
    """
    def __init__(self):
        self._data = PositionalList()

    def __len__(self):
        """ Length method."""
        return len(self._data)

    def is_empty(self):
        """ check if the queue is empty or not."""
        return len(self._data) == 0

    def first(self):
        """ get the first element of the queue."""
        if self._data.is_empty():
            raise Empty('The queue is empty')
        return self._data.first().element()

    def enqueue(self, e):
        """ add an element to the end of the queue.
        :return: the Position of the element just be enqueued.
        """
        return self._data.add_last(e)

    def dequeue(self):
        """ remove the first element of the queue."""
        self._data.delete(self._data.first())

    def delete(self, p):
        """ Delete the element associated with position p."""
        self._data.delete(p)

    def __repr__(self):
        return str(self._data)
Ejemplo n.º 15
0
class UnsortedPriorityQueue(PriorityQueueBase): # base class defines _Item
  """A min-oriented priority queue implemented with an unsorted list."""

  #----------------------------- nonpublic behavior -----------------------------
  def _find_min(self):
    """Return Position of item with minimum key."""
    if self.is_empty():               # is_empty inherited from base class
      raise Exception('Priority queue is empty')
    small = self._data.first()
    walk = self._data.after(small)
    while walk is not None:
      if walk.element() < small.element():
        small = walk
      walk = self._data.after(walk)
    return small

  #------------------------------ public behaviors ------------------------------
  def __init__(self):
    """Create a new empty Priority Queue."""
    self._data = PositionalList()

  def __len__(self):
    """Return the number of items in the priority queue."""
    return len(self._data)

  def add(self, key, value):
    """Add a key-value pair."""
    self._data.add_last(self._Item(key, value))

  def min(self):
    """Return but do not remove (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
    p = self._find_min()
    item = p.element()
    return (item._key, item._value)

  def remove_min(self):
    """Remove and return (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
    p = self._find_min()
    item = self._data.delete(p)
    return (item._key, item._value)

  def __iter__(self):
    """Generate iteration of the map's keys."""
    for item in self._data:
      yield item  # yield the KEY
class SortedPriorityQueue(PriorityQueue):
    """
    Implementation of a PriorityQueue using a sorted PositionalList
    Adds items to the list in order
    """
    def __init__(self):
        """
        Creates an empty PriorityQueue
        """
        self._data = PositionalList()

    def __len__(self):
        """
        returns: the number of items in the PriorityQueue
        """
        return len(self._data)

    def add(self, key, value):
        """
        Adds a key-value pair to the PriorityQueue
        """
        new_item = self._Item(key, value)
        walk = self._data.last()
        while walk is not None and new_item < walk.element():
            walk = self._data.before(walk)
        if walk is not None:
            self._data.add_after(walk, new_item)
        else:
            self._data.add_first(new_item)

    def min(self):
        """
        returns: the (k,v) tuple with the minimum key, without removing it
        """
        if self.is_empty():
            raise Empty('Priority Queue is empty')
        p = self._data.first()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        """
        removes the minimum (k,v) tuple from the priority queue
        returns: the (k,v) tuple
        """
        if self.is_empty():
            raise Empty('Priority Queue is empty')
        p = self._data.first()
        item = self._data.delete(p)
        return (item._key, item._value)
    def top(self, k):
        """Generate sequence of top k elements in terms of access count."""
        if not 0 <= k <= len(self):
            raise ValueError("Illegal value for k")

        # we begin my making copy of original list, as we will modify the temprary list
        temp = PositionalList()
        for item in self._data:  # positional list supports iteration
            temp.add_last(item)

        # we repeatedly find, report, and remove elements with largest count from temp list
        for j in range(k):
            # find and report next highest from temp
            highPos = temp.first()
            walk = temp.after(highPos)
            while walk != None:
                if walk.element()._count > highPos.element()._count:
                    highPos = walk
                walk = temp.after(walk)
            # we have found element with the highest count
            yield highPos.element()._value  # report element to user
            temp.delete(
                highPos)  # remove from temp to get next most accessed element
class UnsortedPriorityQueue(PriorityQueueBase): # base class defines _Item
  """A min-oriented priority queue implemented with an unsorted list."""

  #----------------------------- nonpublic behavior -----------------------------
  def _find_min(self):
    """Return Position of item with minimum key."""
    if self.is_empty():               # is_empty inherited from base class
      raise Empty('Priority queue is empty')
    small = self._data.first()
    walk = self._data.after(small)
    while walk is not None:
      if walk.element() < small.element():
        small = walk
      walk = self._data.after(walk)
    return small

  #------------------------------ public behaviors ------------------------------
  def __init__(self):
    """Create a new empty Priority Queue."""
    self._data = PositionalList()

  def __len__(self):
    """Return the number of items in the priority queue."""
    return len(self._data)

  def add(self, key, value):
    """Add a key-value pair."""
    self._data.add_last(self._Item(key, value))

  def min(self):
    """Return but do not remove (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
    p = self._find_min()
    item = p.element()
    return (item._key, item._value)

  def remove_min(self):
    """Remove and return (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
    p = self._find_min()
    item = self._data.delete(p)
    return (item._key, item._value)
Ejemplo n.º 19
0
class SortedPriorityQueue(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with a sorted list."""

    # ------------------------------ public behaviors ------------------------------
    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)
        walk = self._data.last()  # walk backward look for smaller

        while walk and newest < walk.element():
            walk = self._data.before(walk)

        if not walk:
            self._data.add_first(newest)
        else:
            self._data.add_after(walk, newest)

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.

        Raise Empty exception if empty.
        """
        if self.is_empty():
            raise Empty('Priority Queue is empty')
        first = self._data.first()
        item = first.element()
        return (item._key, item._value)

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.

        Raise Empty exception if empty.
        """
        min = self._data.first()
        item = self._data.delete(min)
        return (item._key, item._value)
class SortedPriorityQueue(PriorityQueueBase): # base class defines _Item
  """A min-oriented priority queue implemented with a sorted list."""

  #------------------------------ public behaviors ------------------------------
  def __init__(self):
    """Create a new empty Priority Queue."""
    self._data = PositionalList()

  def __len__(self):
    """Return the number of items in the priority queue."""
    return len(self._data)

  def add(self, key, value):
    """Add a key-value pair."""
    newest = self._Item(key, value)             # make new item instance
    walk = self._data.last()       # walk backward looking for smaller key
    while walk is not None and newest < walk.element():
      walk = self._data.before(walk)
    if walk is None:
      self._data.add_first(newest)              # new key is smallest
    else:
      self._data.add_after(walk, newest)        # newest goes after walk

  def min(self):
    """Return but do not remove (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
    if self.is_empty():
      raise Empty('Priority queue is empty.')
    p = self._data.first()
    item = p.element()
    return (item._key, item._value)

  def remove_min(self):
    """Remove and return (k,v) tuple with minimum key.

    Raise Empty exception if empty.
    """
    if self.is_empty():
      raise Empty('Priority queue is empty.')
    item = self._data.delete(self._data.first())
    return (item._key, item._value)
Ejemplo n.º 21
0
class SortedPriorityQueue(PriorityQueueBase):
    def __init__(self):
        #empty priority queue
        self._data = PositionalList()

    def __len__(self):
        #number of items in priority queue
        return len(self._data)

    def add(self, key, value):
        #add key-value pair
        #._Item defined by base class
        newest = self._Item(key, value)
        walk = self._data.last()
        #look for smaller key
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)
        else:
            self._data.add_after(walk, newest)

    def min(self):
        #returns but does not remove the tuple with min key
        if self.is_empty():
            raise Empty('Priority queue is empty.')
        p = self._data.first()
        item = p.element()
        return (item._key, item._value)

    def remove_min(self):
        #removes and returns the tuple with minimum key
        if self.is_empty():
            raise Empty('Priority queue is empty')
        item = self._data.delete(self._data.first())
        return (item._key)

    def __iter__(self):
        #iteration of the map's keys
        for item in self._data:
            yield item
Ejemplo n.º 22
0
class SortedListPQ(PriorityQueueBase):  # base class defines _Item
    """A min-oriented priority queue implemented with an unsorted list."""
    def __init__(self):
        """Create a new empty Priority Queue."""
        self._data = PositionalList()

    def __len__(self):
        """Return the number of items in the priority queue."""
        return len(self._data)

    def add(self, key, value):
        """Add a key-value pair."""
        newest = self._Item(key, value)
        walk = self._data.last()
        while walk is not None and newest < walk.element():
            walk = self._data.before(walk)
        if walk is None:
            self._data.add_first(newest)
        else:
            self._data.add_after(walk, newest)

    def min(self):
        """Return but do not remove (k,v) tuple with minimum key.
    Raise Empty exception if empty.
    """
        if self.is_empty():
            raise Empty("Priority queue is empty")
        p = self._data.first()
        item = p.element()
        return item._key, item._value

    def remove_min(self):
        """Remove and return (k,v) tuple with minimum key.
    Raise Empty exception if empty.
    """
        if self.is_empty():
            raise Empty("Priority queue is empty")
        item = self._data.delete(self._data.first())
        return (item._key, item._value)
Ejemplo n.º 23
0
class FavouritesList:

    # positional list stores item intances
    class _Item:

        __slots__ = "_value", "_count"

        def __init__(self, e):
            self._value = e
            self._count = 0

    # return position of item with value e (items should have unique values)
    def _find_position(self, e):
        p = self._data.first()
        while p is not None and p.element()._value != e:
            p = self._data.after(p)
        return p

    # move position of newly inserted item up to the appropriate place
    def _move_up(self, p):
        if p == self._data.first():
            return

        it = self._data.before(p)

        if it.element()._count >= p.element()._count:
            return

        while self._data.before(it) != None and self._data.before(
                it).element()._count < p.element()._count:
            it = self._data.before(it)

        item = self._data.delete(p)
        self._data.add_before(it, item)

        # if p == self._data.first():
        #     return
        #
        # b = self._data.before(p)
        # c = p._element()._count
        #
        # while b.element()._count < c and self._data.before(b) != None:
        #     b = self._data.before(b)
        #
        # e = self.data.delete(p)
        #
        # if b.element()._count < c:
        #     self._data.add_before(b, e)
        # else:
        #     self._data.add_after(b, e)

    def __init__(self):
        self._data = PositionalList()

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

    def is_empty(self):
        return len(self._data) == 0

    def access(self, e):
        p = self._find_position(e)

        if p is None:
            p = self._data.add_last(self._Item(e))

        p.element()._count += 1
        self._move_up(p)

    def remove(self, e):
        p = self._find_position(e)
        if p is not None:
            self._data.delete(p)

    def top(self, k):
        if k < 1 or k > len(self._data):
            raise ValueError("Invalid value for k.")

        p = self._data.first()

        for i in range(k):
            yield p.element()._value
            p = self._data.after(p)
Ejemplo n.º 24
0
class FavoritesList:
    """List of elements ordered from most frequently accessed to least."""

    # ------------------- nested _Item class --------------------------------
    class _Item:
        __slots__ = '_value', '_count'  # make the object lighter-weight in memory

        def __init__(self, e):
            self._value = e  # the user's element
            self._count = 0  # access count initially zero

    # -------------------- nonpublic utilities --------------------------------
    def _find_position(self, e):
        """Search for element e and return its Position (or None if not found).

        Returns:
            walk (Position): Position object.
        """
        walk = self._data.first()  # a Position object
        while walk is not None and walk.element()._value != e:
            walk = self._data.after(walk)
        return walk

    def _move_up(self, p):
        """Move item at Position p earlier in the list based on access count."""
        if p != self._data.first():  # If it's not first, consider moving it...
            cnt = p.element()._count
            walk = self._data.before(p)
            if cnt > walk.element()._count:  # must shift p forward (it's more
                # frequently accessed)
                while (walk != self._data.first()
                       and  # Walk leftward til reach front of list...
                       cnt > self._data.before(walk).element()._count
                       ):  #...or an element that sorts
                    # to a higher position than the element that's being sorted
                    walk = self._data.before(walk)  # Walk one step left
                self._data.add_before(walk,
                                      self._data.delete(p))  # delete/reinsert

    # ------------------------- public methods -------------------------------
    def __init__(self):
        """Create empty list of favorites."""
        self._data = PositionalList()  # will be list of _Item instances

    def __len__(self):
        """Return number of entries on favorites list."""
        return len(self._data)

    def is_empty(self):
        """Return True if list is empty."""
        return len(self._data) == 0
        # Presumably, this can't (or shouldn't) just use _DLB's
        #   inherited-inherited is_empty method because that entire class
        #   is meant to be nonpublic.

    def access(self, e):
        """
        Access element e, thereby increasing its access count.

        e (object): The actual stored item--the _value attribute of the _Item object.
                    Not the _Item object itself (that's not to be accessed from outside the
                    class) and not the Position object. Need not be the identical
                    object in memory; e.g. separate string or int object with same
                    value will be accessed successfully. 
        """
        p = self._find_position(e)  # try to locate existing element
        if p is None:
            p = self._data.add_last(self._Item(e))  # if new, place at end
        p.element()._count += 1  # always increment count
        self._move_up(p)  # Move element forward if needed

    def remove(self, e):
        """Remove element e from the list of favorites."""
        p = self._find_position(e)  # try to locate existing element
        if p is not None:
            self._data.delete(p)  # delete, if found

    def top(self, k):
        """Generate sequence of top k elements in terms of access count.
        Yields an iterator that can be used in a for loop; doesn't return
        anything. 

        Args:
            k (int): Number of elements to include in the list. Must be a
                positive nonzero integer no greater than the length of the list.

        Returns:
            None
        """
        if not 1 <= k <= len(self):
            raise ValueError('Illegal value for k')
        walk = self._data.first()
        for j in range(k):
            item = walk.element()  # element of list is _Item
            yield item._value  # report user's element
            walk = self._data.after(walk)
Ejemplo n.º 25
0
class FavoritesList:
    """A list of elements ordered from most frequently accessed to least."""

    # ----- Class to store an element's value and access frequency. ----- #
    class _Item:
        """Object to store elements' value and access counts."""
        __slots__ = "_value", "_count"

        def __init__(self, e):
            self._value = e  # Element.
            self._count = 0  # To store access count.

    # ----- Non-Public Utilities ----- #
    def _find_position(self, e):
        """Search for element 'e' and return its position, or None if not found."""

        walk = self._data.first()  # Start at header of underlying linked list.
        while (walk is not None) and (walk.element()._value != e):
            walk = self._data.after(walk)
        return walk

    def _move_up(self, p):
        """Move item at position 'p' *earlier* in the list, based on access counts."""

        if p != self._data.first():

            count = p.element()._count()
            walk = self._data.before(p)
            if count > walk.element(
            )._count:  # Need to shift element forward/up the positional list.

                # You're not at the head of the LL & Current count is larger than next count.
                while (walk != self._data.first()) and (
                        count > self._data.before(walk).element()._count):
                    walk = self._data.before(
                        walk
                    )  # Continue backward traversal through linked list.

                self._data.add_before(walk, self._data.delete(
                    p))  # Insert element at correct position in list.

    # ----- Public Methods ----- #
    def __init__(self):
        """Create an empty list of favorites."""
        self._data = PositionalList(
        )  # Will be a list of _Item instances (from nested class above)

    def __len__(self):
        """Return number of elements in favorites list."""
        return len(self._data)

    def is_empty(self):
        """Return True if favorites list is empty."""
        # return self._data.is_empty()
        return len(self._data) == 0

    def access(self, e):
        """Access element 'e', and increase its frequency count."""
        elem_pos = self._find_position(e)

        # Must add element if doesn't currently exist in the favorites list.
        if elem_pos is None:
            elem_pos = self._data.add_last(self._Item(e))

        ## Don't need because we are not returning anything.
        # elem_node = self._data._validate(elem_pos)
        # elem = elem_node._element

        elem_pos.element()._count += 1
        self._move_up(elem_pos)

    def remove(self, e):
        """Remove element 'e' from favorites list."""
        p = self._find_position(e)
        if p is not None:
            self._data.delete(p)

    def top(self, k):
        """Generate a sequence (create a generator for) of the top 'k' elements, with respect to access counts."""

        if not 1 <= k <= len(self):
            raise ValueError("'k' value outside of range.")

        ## Don't need because we are not returning a list, only making a generator.
        # top = list()

        walk = self._data.first()
        for i in range(k):
            item = walk.element()
            elem = item._value
            # top.append(elem)
            yield elem
            walk = self._data.after(walk)
class FavoritesList:
    """List of elements ordered from most frequently accessed to least."""

    # ------------------------------ nested _Item class ------------------------------
    class _Item:
        __slots__ = '_value', '_count'  # streamline memory usage

        def __init__(self, e):
            self._value = e  # the user's element
            self._count = 0  # access count initially zero

    # ------------------------------- nonpublic utilities -------------------------------
    def _find_position(self, e):
        """Search for element e and return its Position (or None if not found)."""
        walk = self._data.first()
        while walk is not None and walk.element()._value != e:
            walk = self._data.after(walk)
        return walk

    def _move_up(self, p):
        """Move item at Position p earlier in the list based on access count."""
        if p != self._data.first():  # consider moving...
            cnt = p.element()._count
            walk = self._data.before(p)
            if cnt > walk.element()._count:  # must shift forward
                while (walk != self._data.first() and
                               cnt > self._data.before(walk).element()._count):
                    walk = self._data.before(walk)
                self._data.add_before(walk, self._data.delete(p))  # delete/reinsert

    # ------------------------------- public methods -------------------------------
    def __init__(self):
        """Create an empty list of favorites."""
        self._data = PositionalList()  # will be list of _Item instances

    def __len__(self):
        """Return number of entries on favorites list."""
        return len(self._data)

    def is_empty(self):
        """Return True if list is empty."""
        return len(self._data) == 0

    def access(self, e):
        """Access element e, thereby increasing its access count."""
        p = self._find_position(e)  # try to locate existing element
        if p is None:
            p = self._data.add_last(self._Item(e))  # if new, place at end
        p.element()._count += 1  # always increment count
        self._move_up(p)  # consider moving forward

    def remove(self, e):
        """Remove element e from the list of favorites."""
        p = self._find_position(e)  # try to locate existing element
        if p is not None:
            self._data.delete(p)  # delete, if found

    def top(self, k):
        """Generate sequence of top k elements in terms of access count."""
        if not 1 <= k <= len(self):
            raise ValueError('Illegal value for k')
        walk = self._data.first()
        for j in range(k):
            item = walk.element()  # element of list is _Item
            yield item._value  # report user's element
            walk = self._data.after(walk)

    def __repr__(self):
        """Create string representation of the favorites list."""
        return ', '.join('({0}:{1})'.format(i._value, i._count) for i in self._data)
Ejemplo n.º 27
0
class FavouritesList:
    """
    An abstract data type storing a sequence of elements in order of their access count
    i.e. the most popular/most accessed elements occur first. Uses a doubly linked list as underlying storage
    """
    class _Item:
        """
        a composite object containing an element of the favourites list as well as its access count
        """
        def __init__(self, e):
            self._value = e
            self._count = 0

    def _find_position(self, e):
        """
        find the position in the list where e is stored or return None
        """
        walk = self._data.first()
        while walk is not None and walk.element()._value != e:
            walk = self._data.after(walk)
        return walk

    def _move_up(self, p):
        """
        consider moving element at position p further ahead in the sequence to preserve the invariant i.e.
        elements of the sequence must be stored in non-increasing order.
        """
        if p != self._data.first():
            cnt = p.element()._count
            walk = self._data.before(p)
            if cnt > walk.element()._count:
                while walk != self._data.first() and cnt > self._data.before(
                        walk).element()._count:
                    walk = self._data.before(walk)
                self._data.add_before(walk, self._data.delete(p))

    def __init__(self):
        self._data = PositionalList()

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

    def is_empty(self):
        return len(self) == 0

    def access(self, e):
        """
        access element e and increase its access count.
        """
        p = self._find_position(e)
        if p is None:
            p = self._data.add_last(self._Item(e))
        p.element()._count += 1
        self._move_up(p)

    def remove(self, e):
        p = self._find_position(e)
        if p is not None:
            self._data.delete(p)

    def top(self, k):
        """
        return an iteration of the top k most accessed elements of the list
        """
        if not 1 <= k <= len(self):
            raise ValueError("Invalid value of k.")
        walk = self._data.first()
        for i in range(k):
            yield walk.element()._value
            walk = self._data.after(walk)
Ejemplo n.º 28
0
class FavoritesList:
    """List of elements ordered from most frequently accessed to least."""

    # ------------------------------ nested _Item class -----------------------
    class _Item:
        __slots__ = "_value", "_count"  # streamline memory usage

        def __init__(self, e):
            self._value = e  # the user's element
            self._count = 0  # access count initially zero

    # ------------------------------- nonpublic utilities ---------------------
    def _find_position(self, e):
        """Search for element e and return its Position (or None if not found)."""
        walk = self._data.first()
        while walk is not None and walk.element()._value != e:
            walk = self._data.after(walk)
        return walk

    def _move_up(self, p):
        """Move item at Position p earlier in the list based on access count."""
        if p != self._data.first():  # consider moving...
            cnt = p.element()._count
            walk = self._data.before(p)
            if cnt > walk.element()._count:  # must shift forward
                while walk != self._data.first() and cnt > self._data.before(walk).element()._count:
                    walk = self._data.before(walk)
                self._data.add_before(walk, self._data.delete(p))  # delete/reinsert

    # ------------------------------- public methods --------------------------
    def __init__(self):
        """Create an empty list of favorites."""
        self._data = PositionalList()  # will be list of _Item instances

    def __len__(self):
        """Return number of entries on favorites list."""
        return len(self._data)

    def is_empty(self):
        """Return True if list is empty."""
        return len(self._data) == 0

    def access(self, e):
        """Access element e, thereby increasing its access count."""
        p = self._find_position(e)  # try to locate existing element
        if p is None:
            p = self._data.add_last(self._Item(e))  # if new, place at end
        p.element()._count += 1  # always increment count
        self._move_up(p)  # consider moving forward

    def remove(self, e):
        """Remove element e from the list of favorites."""
        p = self._find_position(e)  # try to locate existing element
        if p is not None:
            self._data.delete(p)  # delete, if found

    def top(self, k):
        """Generate sequence of top k elements in terms of access count."""
        if not 1 <= k <= len(self):
            raise ValueError("Illegal value for k")
        walk = self._data.first()
        for j in range(k):
            item = walk.element()  # element of list is _Item
            yield item._value  # report user's element
            walk = self._data.after(walk)

    def __repr__(self):
        """Create string representation of the favorites list."""
        return ", ".join("({0}:{1})".format(i._value, i._count) for i in self._data)