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
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))
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))
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)
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)
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
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
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)
class Mesh: '''A polygonal mesh class. Contains a Python list of vertex tuples and a positional list of faces that are themselves Python lists. ''' def __init__(self): self.__verts = list() self.__faces = PositionalList() self.__polygon_types = list( ) # RP: shape of polygon or the name of n-gon self.__numberOfVertices = 0 # RP: total number of vertices self.__totalPolygons = 0 # RP: total number of faces self.__polygons = dict( ) # RP: count of each type of faces, 3 squares, 5 pentagons etc self.__x_minimum = 0 # RP: minimum of x co-ordinates self.__y_minimum = 0 # RP: minimum of y co-ordinates self.__z_minimum = 0 # RP: minimum of z co-ordinates self.__x_maximum = 0 # RP: maximim of x co-ordinates self.__y_maximum = 0 # RP: maximim of y co-ordinates self.__z_maximum = 0 # RP: maximim of z co-ordinates def loadOBJ(self, f): '''Loads data from an OBJ file and stores it in the __verts and __faces data members. Also calculates the X,Y,Z bounds and the counts of face's index sizes. ''' with open(f, 'r') as infile: text = infile.read() lines = text.split('\n') for line_number, line_value in enumerate(lines): if line_value is not '': elements = line_value.split() if elements[0] == 'v': self.__verts += [ (float(elements[1]), float(elements[2]), float(elements[3])) ] self.__numberOfVertices += 1 if elements[0] == 'f': face = list() for vertex_index in elements[1:]: face.append(int(vertex_index)) self.__faces.add_last( face) # RP: ist of vertex indexs, face # RP: In len(face) if-statement, counting the number of each type of polygon, if len(face)=3 or # RP: say triangle already exist, add one to it, else start count from 1 if len(face) in self.__polygon_types: # RP: self.__polygons is the dictionary of total number of each polygons self.__polygons[len(face)] += 1 else: self.__polygon_types.append(len(face)) self.__polygons[len(face)] = 1 # RP: Adding all types of polygon all in the total polygons self.__totalPolygons += 1 def get_stats(self): '''Gets the stats of the Mesh data: - the total number of vertices - the total number of polygons - the number of polygons of each number of sides - the mininum and maximum X, Y, and Z coordinates for the entire mesh ''' # MVM: Hint for the total number of polys of each number of # of sides, use a dictionary. # RP: Made a list of x,y and z elements/coordinates, to get minimum and maximum of each co-ordinates individually x_elements = list() y_elements = list() z_elements = list() for vertex in self.__verts: x_elements.append(vertex[0]) y_elements.append(vertex[1]) z_elements.append(vertex[2]) self.__x_minimum = min(x_elements) self.__y_minimum = min(y_elements) self.__z_minimum = min(z_elements) self.__x_maximum = max(x_elements) self.__y_maximum = max(y_elements) self.__z_maximum = max(z_elements) stats = { "totalVertices": self.__numberOfVertices, "totalPolygon": self.__totalPolygons, "numberOfPolygons": self.__polygons, "minimumXCoordinates": self.__x_minimum, "minimumYCoordinates": self.__y_minimum, "minimumZCoordinates": self.__z_minimum, "maximumXCoordinates": self.__x_maximum, "maximumYCoordinates": self.__y_maximum, "maximumZCoordinates": self.__z_maximum } return stats def writeVTK(self, outfile): '''Writes a VTK legacy ASCII format file from data stored in __verts and __faces. ''' with open(outfile, 'w') as outfile: # RP: First part of vtk file, uptil vertices outfile.write('# vtk DataFile Version 3.0\n') outfile.write('An object\n') outfile.write('ASCII\n') outfile.write('DATASET POLYDATA\n') outfile.write('POINTS ' + str(self.__numberOfVertices) + ' float\n') for vertex in self.__verts: outfile.write( str(vertex[0]) + ' ' + str(vertex[1]) + ' ' + str(vertex[2]) + '\n') outfile.write('\n') # RP: As in the dictionary {key:value}, typeOfPolygon(tri/4/penta...gon) is the key and numberOfThosePolygon # is the value, which together is used to calculate total points for vtk file. total_points = 0 for typeOfPolygon, numberOfThosePolygon in self.__polygons.items(): total_points += (typeOfPolygon + 1) * numberOfThosePolygon outfile.write('POLYGONS ' + str(self.__totalPolygons) + ' ' + str(total_points) + '\n') for face in self.__faces: outfile.write(str(len(face)) + ' ') for vertex_index in face: outfile.write(str(vertex_index - 1) + ' ') outfile.write('\n') def triangularize(self): '''Triangularizes any non-triangles in the face list. It modifes the list be replacing non-triangles with two or more triangles. The modifcation occurs at the site of the non-triangle.''' # RP: Because in Triangulation, we only need to print number of triangles if 3 not in self.__polygon_types: self.__polygons[3] = 0 self.__polygon_types.append(3) pos = self.__faces.first( ) # RP: setting position of the first list in the PositionalList(self.__faces) while pos is not None: # RP: will do one face at a time face = pos.element( ) # RP: accessing the elements in that position of the list calling it face if len(face) > 3: for n in range(2, len(face) - 1): # RP: if face is [1 2 3 4] say in square triangle = list() triangle.append(face[0]) # RP: here goes, face[0]=1 triangle.extend( face[n:n + 2] ) # RP: here goes a slice of face[2:4], which is 3,4, and is # extended to previous one, making it [1 3 4] face as triangle self.__faces.add_before( pos, triangle ) # RP: Now adding that face [1 3 4] before [1 2 3], similarly all the # triangle face is added before the place where it is cut self.__polygons[3] += 1 self.__totalPolygons += 1 self.__faces.replace(pos, face[0:3]) # RP: Slice of face [1 2 3] self.__polygons[3] += 1 pos = self.__faces.after( pos) # RP: Giving the position to the next one new_polygons = {3: self.__polygons[3]} self.__polygons = new_polygons def __repr__(self): '''Print user-friendly representation of the Mesh object.''' # MVM: have this call get_stats() output = 'This is a 3D object which consists of {} type(s) of polygon(s).\n'.format( len(self.__polygons)) output += 'Polygon stats:\n' try: output += '\tTotal Vertices:{0:>16}\n'.format( self.get_stats()['totalVertices']) output += '\tTotal Polygons:{0:>16}\n'.format( self.get_stats()['totalPolygon']) for key, values in self.get_stats()['numberOfPolygons'].items(): output += '\tTotal {0} sided polygon:{1:>9}\n'.format( key, values) output += '\tMinimum x coordinate:{0:>10.2f}\n'.format( self.get_stats()['minimumXCoordinates']) output += '\tMaximum x coordinate:{0:>10.2f}\n'.format( self.get_stats()['maximumXCoordinates']) output += '\tMinimum y coordinate:{0:>10.2f}\n'.format( self.get_stats()['minimumYCoordinates']) output += '\tMaximum y coordinate:{0:>10.2f}\n'.format( self.get_stats()['maximumYCoordinates']) output += '\tMinimum z coordinate:{0:>10.2f}\n'.format( self.get_stats()['minimumZCoordinates']) output += '\tMaximum z coordinate:{0:>10.2f}\n'.format( self.get_stats()['maximumZCoordinates']) except: output += 'NO DATA\n' return output
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)
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)
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)
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' # 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)
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)