Python OOP Disjoint Set Performance - python

I built a disjoint-set data structure for use with Kruskal's MST algorithm. I need to load and then union a graph with 200k interconnected nodes and I think my data structure implementation is a bottleneck.
Do you have an suggestions for how to improve performance? I think my find method might be problematic.
class partition(object):
def __init__(self, element=None):
self.size = 0
if element == None:
self.contents = set()
self.representative = None
else:
self.contents = {element}
self.representative = element
self.size = 1
def find(self, element):
return element in self.contents
def add(self, partition):
self.contents = self.contents.union(partition)
self.size = len(self.contents)
def show(self):
return self.contents
def __repr__(self):
return str(self.contents)
class disjoint_set(object):
def __init__(self):
self.partitions_count = 0
self.forest = {}
def make_set(self, element):
if self.find(element) == False:
new_partition = partition(element)
self.forest[new_partition.representative] = new_partition
self.partitions_count += 1
def union(self, x, y):
if x != y:
if self.forest[x].size < self.forest[y].size:
self.forest[y].add(self.forest[x].show())
self.delete(x)
else:
self.forest[x].add(self.forest[y].show())
self.delete(y)
def find(self, element):
for partition in self.forest.keys():
if self.forest[partition].find(element):
return self.forest[partition].representative
return False
def delete(self, partition):
del self.forest[partition]
self.partitions_count -= 1
if __name__ == '__main__':
t = disjoint_set()
t.make_set(1)
t.make_set(2)
t.make_set(3)
print("Create 3 singleton partitions:")
print(t.partitions_count)
print(t.forest)
print("Union two into a single partition:")
t.union(1,2)
print(t.forest)
print(t.partitions_count)
EDIT:
After reading the comments and doing additional research I realized how poorly designed my original algorithm was. I started over from scratch and put this together. I put all the partitions into a single hash table and used path compression in the find(). How does this look and are there any glaring problems I should address?
class disjoint_set(object):
def __init__(self):
self.partitions_count = 0
self.size = {}
self.parent = {}
def make_set(self, element):
if self.find(element) == False:
self.parent[element] = element
self.size[element] = 1
self.partitions_count += 1
def union(self, x, y):
xParent = self.find(x)
yParent = self.find(y)
if xParent != yParent:
if self.size[xParent] < self.size[yParent]:
self.parent[xParent] = yParent
self.size[yParent] += self.size[xParent]
self.partitions_count -= 1
else:
self.parent[yParent] = xParent
self.size[xParent] += self.size[yParent]
self.partitions_count -= 1
def find(self, element):
if element in self.parent:
if element == self.parent[element]:
return element
root = self.parent[element]
while self.parent[root] != root:
root = self.find(self.parent[root])
self.parent[element] = root
return root
return False
if __name__ == '__main__':
t = disjoint_set()
t.make_set(1)
t.make_set(2)
t.make_set(3)
t.make_set(4)
t.make_set(5)
print("Create 5 singleton partitions")
print(t.partitions_count)
print("Union two singletons into a single partition")
t.union(1,2)
print("Union three singletones into a single partition")
t.union(3,4)
t.union(5,4)
print("Union a single partition")
t.union(2,4)
print("Parent List: %s" % t.parent)
print("Partition Count: %s" % t.partitions_count)
print("Parent of element 2: %s" % t.find(2))
print("Parent List: %s" % t.parent)

I guess your find implementation is not running effienctly, which it supposed to be.
Following changes may help.
class disjoint_set(object):
def __init__(self):
self.partitions_count = 0
self.forest = {}
self.parent = {}
def make_set(self, element):
if not self.find(element):
new_partition = partition(element)
self.parent[element] = element
self.forest[new_partition.representative] = new_partition
self.partitions_count += 1
def union(self, x, y):
if x != y:
if self.forest[x].size < self.forest[y].size:
self.forest[y].add(self.forest[x].show())
#Update parent details
self.parent[self.forest[x].representative] = self.forest[y].representative
self.delete(x)
else:
self.forest[x].add(self.forest[y].show())
#Update parent details
self.parent[self.forest[y].representative] = self.forest[x].representative
self.delete(y)
def find(self, element):
if self.parent[element] == element:
return element
else:
return find(element)
The code can be still optimized with path-compression to have disjoint_set.find to run in O(1). I guess O(log n) still is good for big numbers.
Another bottleneck could be your union function. Especially the add function implementation.
def add(self, partition):
self.contents = self.contents.union(partition)
Try using an update method of set (which is an inplace union). I think is causing lot of memory overhead for huge no.of nodes. Something like
self.contents.update(partition)
There is a nice discussion on set union and update functions here.
Hope it helps!

Related

How to find all path of a graph

Update
Thanks to the comments of some community members, I realize that there are some similar problems, but they may a bit different, please allow me to explain it further.
I actually hope to use the same method in a real problem, So briefly:
Reuse of edges in differernt path is completely allowed
a unique(or a new) path from A to B is defined as a collection of vertices that have any different vertices.
Let me use a quiz from Python data structure and algorithm analysis by Bradley .N Miller and David L. Ranum to expain my qusetion.
Quesion:
Consider the task of converting the word FOOL to SAGE, also called word ladder problem. In solving
In the word ladder problem, only one letter must be replaced at a time, and the result of each step must be a word, not non-existent.
Input:
FOUL
FOOL
FOIL
FAIL
COOL
FALL
POOL
PALL
POLL
POLE
PALE
PAGE
SALE
POPE
POPE
SAGE
We can easily find the path from FOOL to SAGE, as Bradley showed:
enter image description here
and I used Breadth First Search (BFS) to solve probem:
class Vertex:
def __init__(self, key, value = None):
self.id = key
self.connectedTo = {}
self.color = 'white'
self.dist = sys.maxsize
self.pred = []
self.disc = 0
self.fin = 0
self.value = value,
#self.GraphBulided = False
self.traverseIndex = 0
self.predNum = 0
def addNeighbor(self, nbr, weight=0):
self.connectedTo[nbr] = weight
def __str__(self):
return '{} connectedTo: {}'.format(self.id, \
str([x.id for x in self.connectedTo]))
def setColor(self, color):
self.color = color
def setDistance(self, d):
self.dist = d
#I want store all Pred for next traverse so I use a list to do it
def setPred(self, p, list = False):
if not list:
self.pred = p
else:
self.pred.append(p)
self.predNum += 1
def setDiscovery(self,dtime):
self.disc = dtime
def setFinish(self,ftime):
self.fin = ftime
#def setGraphBulided(self, tag = True):
# self.GraphBulided = tag
def getFinish(self):
return self.fin
def getDiscovery(self):
return self.disc
def getPred(self):
if isinstance(self.pred, list):
if self.traverseIndex < self.predNum:
return self.pred[self.traverseIndex]
else:
return self.pred[-1]
else:
return self.pred
def __hash__(self):
return hash(self.id)
def getPredById(self):
if self.traverseIndex < self.predNum and isinstance(self.pred, list):
pred = self.pred[self.traverseIndex]
self.traverseIndex += 1
print("vertix {}: {} of {} preds".format(self.id, self.traverseIndex, self.predNum))
return [pred, self.traverseIndex]
else:
pred = None
return [pred, None]
def getCurrPredStaus(self):
#if not self.pred:
# return None
return self.predNum - self.traverseIndex
def getDistance(self):
return self.dist
def getColor(self):
return self.color
def getConnections(self):
return self.connectedTo.keys()
def getId(self):
return self.id
def getWeight(self, nbr):
return self.connectedTo[nbr]
def getValue(self):
return self.value
def findPath(self, dest):
pass
class Graph:
def __init__(self):
self.vertList = {}
self.numVertics = 0
self.verticsInSerach = set()
self.GraphBulided = False
def addVertex(self, key, value = None):
self.numVertics = self.numVertics + 1
newVertex = Vertex(key, value=value)
self.vertList[key] = newVertex
return newVertex
def getVertex(self, n):
if n in self.vertList:
return self.vertList[n]
else:
return None
def __contains__(self, n):
return n in self.vertList
def addEdge(self, f, t, cost = 0, fvalue = None, tvalue = None):
if f not in self.vertList:
nv = self.addVertex(f, fvalue)
if t not in self.vertList:
nv = self.addVertex(t, tvalue)
self.vertList[f].addNeighbor(self.vertList[t], cost)
def setGraphBulided(self, tag = True):
self.GraphBulided = tag
def getVertices(self):
return self.vertList.keys()
def setGraphBulided(self, tag = True):
self.GraphBulided = tag
def setSerachedVertixs(self, vertix):
self.verticsInSerach.add(vertix)
def getGraphBulided(self):
return self.GraphBulided
def getSerachedVertixs(self):
return self.verticsInSerach
def __iter__(self):
return iter(self.vertList.values())
def __hash__(self):
hashIds = [x for x in self.getVertices()]
if len(hashIds) > 0 and hashIds[0]:
return hash(', '.join(hashIds))
else:
return None
Here are some additional functions for building graphs
def buildGraph(wordFile, DFSgraph = False):
d = {}
g = Graph()
if DFSgraph:
g = DFSGraph()
wfile = open(wordFile)
for line in wfile:
word = line[:-1]
for i in range(len(word)):
bucket = word[:i] + '_' + word[i+1:]
if bucket in d:
d[bucket].append(word)
else:
d[bucket] = [word]
for bucket in d.keys():
for word1 in d[bucket]:
for word2 in d[bucket]:
if word1 != word2:
g.addEdge(word1, word2)
wfile.close()
return g
class Queue:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def enqueue(self, item):
self.items.insert(0,item)
def dequeue(self):
return self.items.pop()
def size(self):
return len(self.items)
def bfs(g, start, listpred = False):
start.setDistance(0)
start.setPred(None)
vertQueue = Queue()
vertQueue.enqueue(start)
while (vertQueue.size() > 0):
currentVert = vertQueue.dequeue()
if currentVert.getConnections():
g.setSerachedVertixs(currentVert)
for nbr in currentVert.getConnections():
#print('sreach {}'.format(currentVert.getId()))
if (nbr.getColor() == 'white' or nbr.getColor() == 'gray'):
nbr.setColor('gray')
nbr.setDistance(currentVert.getDistance() + 1)
if nbr.predNum > 0 and currentVert.getId() not in [x.getId() for x in nbr.pred]:
nbr.setPred(currentVert, listpred)
elif nbr.predNum == 0:
nbr.setPred(currentVert, listpred)
vertQueue.enqueue(nbr)
currentVert.setColor('black')
Therefore, we can easily find the shortest path we need (If we only store one pred for one vertix).
wordGraph = buildGraph('fourletterwords1.txt', DFSgraph=False)
bfs(wordGraph, wordGraph.getVertex('FOOL'), listpred=True)
def traverse(y):
x=y
while(x.getPred()):
print(x.getPred())
x = x.getPred()
print(x.getId())
traverse(wordGraph.getVertex('SAGE'))
However, I still don't know how to trace all the paths correctly, can you give me some suggestions?
FIND path from src to dst ( Dijkstra algorithm )
ADD path to list of paths
LOOP P over list of paths
LOOP V over vertices in P
IF V == src OR V == dst
CONTINUE to next V
COPY graph to working graph
REMOVE V from working graph
FIND path from src to dst in working graph( Dijkstra algorithm )
IF path found
IF path not in list of paths
ADD path to list of paths

Storing actions in a stack for 'undo' purpose

Because stack allows to either push or pop, it is suitable to redo actions by just simply popping the latest action by the user. I have a stack class where:
class Node:
def __init__(self,item,the_next = None):
self.item = item
self.next = the_next
def __str__(self):
return str(self.item)
class LinkedStack:
def __init__(self):
self.top = None
self.count = 0
def __len__(self):
return self.count
def is_empty(self):
return self.count == 0
def isFull(self):
return False
def reset(self):
self.top = None
self.count = 0
def __str__(self):
current = self.top
ans = ""
while not (current is None):
ans += str(current)
ans += '\n'
current = current.next
return ans
def _get_node(self,index):
if 0<= index< len(self):
current = self.top
while index>0:
current = current.next
index -=1
return current
def pop(self):
if self.is_empty():
raise StopIteration("Stack is empty")
output = self.top.item
self.top = self.top.next
self.count -=1
return output
def push(self,item):
newNode = Node(item)
newNode.next = self.top
self.top = newNode
self.count +=1
if __name__ == "__main__":
L = LinkedStack()
and in another file, i import the stack from above and try to implement the undo action.
from Stack import LinkedStack
class Editor:
def __init__(self):
self.count = 0
self._list = LinkedList()
self._stack = LinkedStack()
def command(self,userCommand):
userCommand = userCommand.split(' ')
try:
if userCommand[0] == 'insert':
position = int(userCommand[1])
if len(userCommand) ==1:
raise Exception('no num is given')
textInput = input("Enter your text:")
self._stack.push(self.insertText(position,textInput)) #I'm thinking of adding the action into the stack by pushing it.
print(self._list)
pass
except Exception:
print('?')
if userCommand[0] == 'undo': #here if they choose to undo, by right i just pop the last action from the stack
self._stack.pop()
if __name__ == '__main__':
myCommand = Editor()
while True:
command = input('Enter an option:')
if command.lower() == 'quit':
break
else:
myCommand.command(command)
because I'm merely undoing actions, i thought of adding the command actions into a stack. if you take a look at the insert command above, where i added a comment, am i doing it correctly? Because I'm running out of ideas.
By the way, the insertText is a function which is working and I'm not planning to paste it here as it's getting lengthy. LinkedList() is just a linked list class i imported from another file as well.
The 'undo' doesn't seemed to revert the state. For example, if my LinkedList() contains:
1
2
3
4
None
and if i use the insert function to insert another number, 7 at index 1
1
7
2
3
4
None
and if i undo the action, I'm supposed to have:
1
2
3
4
None

Implement a queue with 2 stacks python and analyze the running time

I've been going over some of the many coding interview questions.
I was wondering about implementing a queue using two stacks in Python. I'm working on algorithm question to implement a queue with two stacks for purposes of understanding both data structures.
I have the below:
class QueueTwoStacks:
def __init__(self):
self.in_stack = []
self.out_stack = []
def enqueue(self, item):
self.in_stack.append(item)
def dequeue(self):
if len(self.out_stack) == 0:
# Move items from in_stack to out_stack, reversing order
while len(self.in_stack) > 0:
newest_in_stack_item = self.in_stack.pop()
self.out_stack.append(newest_in_stack_item)
# If out_stack is still empty, raise an error
if len(self.out_stack) == 0:
raise IndexError("Can't dequeue from empty queue!")
return self.out_stack.pop()
What is the runtime analysis for this one?
Why is it true that we can get O(m)O(m) runtime for mm function calls.
Am I assuming have a stack implementation and it gives O(1)O(1) time push and pop?
I appreciate your explanation for this. thank you.
Yes. We can Optimize for the time cost of m function calls on your queue. This optimization can be any mix of enqueue and dequeue calls.
Assume you already have a stack implementation and it gives O(1)O(1) time push and pop.
#
#
class Stack():
def __init__(self):
self.stk = []
def pop(self):
"""raises IndexError if you pop when it's empty"""
return self.stk.pop()
def push(self, elt):
self.stk.append(elt)
def is_empty(self):
return len(self.stk) == 0
def peek(self):
if not self.stk.is_empty():
return self.stk[-1]
class Queue():
def __init__(self):
self.q = Stack() # the primary queue
self.b = Stack() # the reverse, opposite q (a joke: q vs b)
self.front = None
def is_empty(self):
return self.q.is_empty()
def peek(self):
if self.q.is_empty():
return None
else:
return self.front
def enqueue(self, elt):
self.front = elt
self.q.push(elt)
def dequeue(self):
"""raises IndexError if you dequeue from an empty queue"""
while not self.q.is_empty() > 0:
elt = self.q.pop()
self.b.push(elt)
val = self.b.pop()
elt = None
while not self.b.is_empty() > 0:
elt = self.b.pop()
self.q.push(elt)
self.front = elt
return val
# Now let's test
class TestQueueTwoStacks(unittest.TestCase):
def setUp(self):
self.q = Queue()
def test_queuedequue(self):
"""queue up 5 integers, check they are in there, dequeue them, check for emptiness, perform other blackbox and whitebox tests"""
self.assertTrue(self.q.is_empty())
self.assertTrue(self.q.q.is_empty())
self.assertTrue(self.q.b.is_empty())
l = range(5)
for i in l:
self.q.enqueue(i)
self.assertEqual(4, self.q.peek())
self.assertEqual(l, self.q.q.stk)
s = []
l.reverse()
for i in l:
elt = self.q.dequeue()
s.append(elt)
self.assertTrue(self.q.is_empty())
self.assertTrue(self.q.q.is_empty())
self.assertTrue(self.q.b.is_empty())
l.reverse()
self.assertEqual(s, l)
self.assertEqual([], self.q.b.stk)
self.assertEqual([], self.q.q.stk)
if __name__ == "__main__":
# unittest.main()
suite = unittest.TestLoader().loadTestsFromTestCase(TestQueueTwoStacks)
unittest.TextTestRunner(verbosity=2).run(suite)

Circular Queue Structure ( array-backed)

I need some help in writing a python program that will implement a circular queue data structure (array-backed). I've completed a few of the methods already but I'm a bit stumped when it comes to adding and taking things away from the queue, as well as checking the values within it. I believe this is of the first-in-first-out structure. Here's what I have for the body so far
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.queue = []
self.head = -1
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
self.head = 0
x = self.queue.pop(0)
if self.head == self.tail:
self.head = -1
self.tail = -1
else:
self.tail -= 1
self.count -= 1
#self.head += 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.queue.append(item)
self.tail += 1
def __str__(self):
return " ".join([str(v) for v in self.queue])
def resize(self, new_limit):
new_q = [None]*self.limit
old_q = self.queue
for i in range(len(old_q)):
new_q[i] = old_q[i]
self.limit = new_limit
self.queue = new_q
def empty(self):
return 0 == self.count
def iter(self):
listt = []
for v in self.queue:
listt.append(v)
return listt
What I 've written thus far makes the most sense to me but if I were to test this with the following code block I'd get an error saying 10 != 4. This code will fail the 9th line of the test, tc.assertEqual(q.data.count(None), 4) I'm unsure why my code is producing the value 10 at this time. What would allow for this class to pass the given test?
from unittest import TestCase
tc = TestCase()
q = Queue(10)
for i in range(6):
q.enqueue(i)
tc.assertEqual(q.data.count(None), 4)
for i in range(5):
q.dequeue()
tc.assertFalse(q.empty())
tc.assertEqual(q.data.count(None), 9)
tc.assertEqual(q.head, q.tail)
tc.assertEqual(q.head, 5)
for i in range(9):
q.enqueue(i)
with tc.assertRaises(RuntimeError):
q.enqueue(10)
for x, y in zip(q, [5] + list(range(9))):
tc.assertEqual(x, y)
I'm pretty sure that all the code using self.queue is wrong. That attribute isn't needed at all. The whole point of the data attribute is to use it to store the values. Use the indexes head and tail to figure out where in data to put things (and where to take them from):
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.head = 0
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
x = self.data[self.head]
self.head = (self.head + 1) % self.limit
self.count -= 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.tail = (self.tail + 1) % self.limit
self.data[self.tail] = item
def __str__(self):
return " ".join([str(v) for v in self]) # use __iter__
def resize(self, new_limit):
if new_limit < self.count:
raise RuntimeError
new_data = [None]*new_limit
for i, item in enumerate(self):
new_data[i] = item
self.data = new_data
self.head = 0
self.tail = self.count - 1
def empty(self):
return 0 == self.count
def __bool__(self): # this is better than empty()
return self.count != 0
def __iter__(self): # renamed from iter so you can use it in a for loop
for i in range(self.count):
return self.data[(self.head + i) % self.limit]
You should probably also have a __len__ method.
I'd get an error stating that the Queue class doesn't have a data attribute
I don't have the error you mention when running your test on your code.
If for some reasons you don't want to use built-in collections.deque module, here is an example of how you can implement your own circular buffer:
"""
Example of circular buffer using regular list
"""
class CircularBuffer:
def __init__(self, size):
self.buffer = [None] * size
self.size = size
self.count = 0
self.tail = 0
self.head = 0
#property
def is_empty(self):
return self.count == 0
#property
def is_full(self):
return self.count == self.size
def __len__(self):
return self.count
def add(self, value):
# if buffer is full overwrite the value
if self.is_full:
self.tail = (self.tail + 1) % self.size
else:
self.count += 1
self.buffer[self.head] = value
self.head = (self.head + 1) % self.size
def remove(self):
if self.count == 0:
raise Exception("Circular Buffer is empty")
value = self.buffer[self.tail]
self.tail = (self.tail + 1) % self.size
self.count -= 1
return value
def __iter__(self):
index = self.tail
counter = self.count
while counter > 0:
yield self.buffer[index]
index = (index + 1) % self.size
counter -= 1
def __repr__(self):
return "[]" if self.is_empty else "[" + ",".join(str(i) for i in self) + "]"

How can I create a running average of the last N items in a time series?

My basic idea was to create a linked list, and as each new value comes in, add 1/N times the new value and subtract 1/N times the first value, then move the pointer to first along by one and free the memory that had been associated with first.
This won't ultimately be implemented in Python but just to get the process clear in my head, I tried to write it in Python, but my implementation is flawed. Do I need a doubly linked list for this? Is there an alternative approach (not linked-list based) that would be better?
Here's my attempt so far:
class Link:
def __init__(self,val):
self.next = None
self.value = val
class LinkedList:
def __init__(self,maxlength):
self.current_link = None
self.maxlength = maxlength
self.sum = 0.
self.average = None
self.length = 0
self._first_link = None
def add_link(self,val):
new_link = Link(val)
new_link.next = self.current_link
self.current_link = new_link
if self._first_link is None:
self._first_link = self.current_link
self.sum += val
if self.length < self.maxlength:
self.length += 1
else:
self.sum -= self._first_link.value
self._first_link = self._first_link.next # this line is flawed
self.average = self.sum/self.length
def get_first(self):
return self._first_link.value
# Main
ll = LinkedList(5)
for ii in xrange(10):
ll.add_link(ii)
print ii,ll.get_first(),ll.average
The problem is that _first_link gets set to a value that doesn’t have a next. That is, _first_link gets set to the first item that's added, but its next is None, so I don't see how to move it along by 1 as I want to. This is what makes me wonder if a doubly linked list is needed.
I'd appreciate any advice.
I think the simplest implementation is to use a circular linked list (a.k.a. a ring):
class Link(object):
def __init__(self, value=0.0):
self.next = None
self.value = value
class LinkedRing(object):
def __init__(self, length):
self.sum = 0.0
self.length = length
self.current = Link()
# Initialize all the nodes:
last = self.current
for i in xrange(length-1): # one link is already created
last.next = Link()
last = last.next
last.next = self.current # close the ring
def add_val(self, val):
self.sum -= current.value
self.sum += val
self.current.value = val
self.current = self.current.next
def average(self):
return self.sum / self.length
# Test example:
rolling_sum = LinkedRing(5)
while True:
x = float(raw_input())
rolling_sum.add_val(x)
print(">> Average: %f" % rolling_sum.average())
You can implement this using collections.deque and the numerically stable math for maintaining running averages:
import collections
class AveragingBuffer(object):
def __init__(self, maxlen):
assert( maxlen>1)
self.q=collections.deque(maxlen=maxlen)
self.xbar=0.0
def append(self, x):
if len(self.q)==self.q.maxlen:
# remove first item, update running average
d=self.q.popleft()
self.xbar=self.xbar+(self.xbar-d)/float(len(self.q))
# append new item, update running average
self.q.append(x)
self.xbar=self.xbar+(x-self.xbar)/float(len(self.q))
if __name__=="__main__":
import scipy
ab=AveragingBuffer(10)
for i in xrange(32):
ab.append(scipy.rand())
print ab.xbar, scipy.average(ab.q), len(ab.q)
Okay, I thought of a solution that works in O[1] time. I'm still curious if anyone has a linked-list-based solution, but this solution avoids the LL entirely:
class Recent:
def __init__(self,maxlength):
self.maxlength = maxlength
self.length = 0
self.values = [0 for ii in xrange(maxlength)]
self.index = 0
self.total = 0.
self.average = 0.
def add_val(self,val):
last = self.values[self.index%self.maxlength]
self.values[self.index%self.maxlength] = val
self.total += val
self.total -= last
if self.length < self.maxlength:
self.length += 1
self.average = self.total / self.length
self.index += 1
def print_vals(self):
print ""
for ii in xrange(self.length):
print ii,self.values[ii%self.maxlength]
print "average:",self.average
# Example to show it works
rr = Recent(5)
for ii in xrange(3):
rr.add_val(ii)
rr.print_vals()
for ii in xrange(13):
rr.add_val(ii)
rr.print_vals()

Categories

Resources