Circular Buffer Python implementation - python

I wrote the code for a circular buffer for an interviewstreet question. But as it happened, two testcases passed and the others are failing. The failure of the cause: index out f range. I tried several testcases after that to reproduce the failure. Unfortunately none of them reproduce the error. Here is the code.
Implement a circular buffer of size N. Allow the caller to append, remove and list the contents of the buffer. Implement the buffer to achieve maximum performance for each of the operations.
"A" n - Append the following n lines to the buffer. If the buffer is full they replace the older entries.
"R" n - Remove first n elements of the buffer. These n elements are the ones that were added earliest among the current elements.
"L" - List the elements of buffer in order of their inserting time.
"Q" - Quit.
class circbuffer():
#initialization
def __init__(self,size):
self.maximum=size
self.data=[]
self.current=0
#appending when the buffer is not full
def append(self,x):
if len(self.data)==self.maximum:
self.current=0
self.data[self.current]=x
self.current=(self.current+1)%self.maximum
self.__class__=bufferfull
else:
self.data.append(x)
def remove(self,x):
if self.data:
self.data.pop(0)
def cget(self):
return self.data
class bufferfull:
def append(self,x):
if len(self.data)<self.maximum:
self.data.insert(self.current, x)
else:
self.data[self.current]=x
self.current=(self.current+1)%self.maximum
def remove(self,x):
if self.data:
if self.current>len(self.data):
self.current=0
self.data.pop(self.current)
def cget(self):
return self.data[self.current:]+self.data[:self.current]
n=input()
buf=circbuffer(n)
outputbuf=[]
while True:
com=raw_input().split(' ')
if com[0]=='A':
n=int(com[1])
cominput=[]
for i in xrange(n):
cominput.append(raw_input())
for j in cominput:
buf.append(j)
elif com[0]=="R":
n=int(com[1])
for i in range(n):
buf.remove(i)
elif com[0]=="L":
for i in buf.cget():
outputbuf.append(i)
elif com[0]=="Q":
break
for i in outputbuf:
print i
The error is pointing to self.data.pop(self.current) in class bufferfull. I cannot get the test data from the interviewstreet people. I am trying to come up with testcase myself to reproduce the error.
Any insights?

One bug is here:
def remove(self,x):
if self.data:
if self.current>len(self.data):
self.current=0
self.data.pop(self.current)
If self.current == len(self.data), you'll try to pop a non-existent element.
As a general remark, your implementation is way too complicated and for that reason wouldn't score very highly in my book (others might view this differently). #9000's comment to your question sums it up nicely:
Keep it simple. Don't be clever when you can be straightforward in the same number of lines. All you need is a head pointer, a tail pointer, and a list of a fixed size. You don't need any fancy metaprogramming stuff whatsoever. – #9000

It looks like you are trying to stop the index out of range error with the code below, but the condition you are checking is wrong.
if self.current > len(self.data):
self.current = 0
self.data.pop(self.current)
If you call self.data.pop(len(self.data)) you will definitely get that error since lists are 0-indexed. You probably meant:
if self.current >= len(self.data):
self.current = 0
self.data.pop(self.current)

Related

Creating custom iterators in Python to search for sublists within large datasets

I'm learning/experimenting with iterators/generators in Python to create a fast search function that can search a large data set for a subset from front to back and back to front simultaneously. I've created a Search Class that I intend to thread its instances so they perform a search in parallel. I am trying to understand the usefulness of generators and want to know if this is a situation where they are in fact useful. The way I have it set up, the dataset must still be loaded into memory. Is there a way to do this where the entire dataset doesn't have to be stored in a variable. Any guidance on my approach to this idea would be greatly appreciated!
class Search:
def __init__(self, dataset):
self.data = dataset
self.index = 0
self.end = len(dataset) - 1
def __iter__(self):
while self.index <= self.end:
yield self.index
self.index += 1
def __reversed__(self):
i = self.end
while i >= self.index:
yield i
i -= 1
def search(self, subset, reverse=False):
switch = (iter(self), reversed(self))
for index in switch[reverse]:
if self.data[index] != subset[0]:
continue
else:
sub = slice(index, index + len(subset))
if self.data[sub] == subset:
result = index
break
else:
result = 'Not Found!'
return result
x = Search(large_data)
#thread_1:
x.search(sublist)
#thread_2:
x.search(sublist, reverse=True)
As I understand your question, you need iteration in the dataset loading function. And here it depends, where does the data come from. For files and databases you will find easy solutions in the documentation. If you are using some web API, you may use pagination.

Tree Building Logic Trouble

I am writing a simple app that incorporates a tree that represents the English language. I have done something similar in C++, but this is my first venture at building a tree in Python.
englishWords = []
englishFile = open("english.txt")
for line in englishFile:
englishWords.append(line.rstrip())
class Node:
def __init__(self, value):
self.Value = value
self.checked = False
self.Pointers = []
self.numPointers = 0
def addNode(self, value):
x = Node(value)
self.Pointers.append(x)
return x
headString = "HEAD"
Head = Node(headString)
def buildPointers(parent, info, nodeList):
x = 0
y = len(nodeList)
while x < y :
if parent.numPointers == 0:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
buildPointers(newNode, nodeList[x+1], nodeList)
break
else:
for i in parent.Pointers:
if info == i.Value:
buildPointers(i, nodeList[x+1], nodeList)
continue
else:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
buildPointers(newNode, nodeList[x+1], nodeList)
continue
def treeBuild(lyst):
for i in lyst:
iList = list(i)
buildPointers(Head, iList[0], iList)
treeBuild(englishWords)
As soon as I run the code Windows says "python.exe has stopped running" it's probably something simple that I have overlooked, so feel free to rip into me or the way I wrote this. I would love any criticism that will help make me a better programmer.
Basically this isn't really pythonic, numerous errors here but I guess the main issue would be using too much recursion, something python "out of the box" isn't very good at.
It limits default recursion depth to 1000 steps. and you probably need more. here is a question and answer explaining how to change this default.
also another good advice would be changing the recursion to use generators like in this blog post
p.s: since you don't change the value of x the while loop might run forever in some cases wouldn't it? (I didn't fully understand the algorithm so I'm not sure)
EDIT: to make this a little more pythonic I would change the populating part to use with context manager:
with open("english.txt") as english_file:
for line in english_file ..
BTW a much better way, not loading million strings into a list would be changing the populating part to a generator function, yielding an english word everytime - much more efficient and pythonic. you can read about context managers and generator functions here
Another edit: learining idiomatic python The best place to start would be opening a python shell and:
import this
the "zen of python" would appear.
a good opinionated guide to modern python development including libs, best practice, reading recommendations and writing idomatic python would be Hitchhikers guide to python by kenneth reitz.
and a similar source, more focused one, is writing idiomatic Python
good luck!
You're not actually reducing the nodeList when you recurse causing the infinite recursion. You will also not break out of the loop properly when you finish processing a word. The following buildnodelist completes at the very least. I won't guarantee that it works as desired though since I only modified some blocking lines:
def buildPointers(parent, info, nodeList):
if parent.numPointers == 0:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
if len(nodeList) > 1:
buildPointers(newNode, nodeList[x+1], nodeList[1:])
else:
for i in parent.Pointers:
if info == i.Value:
if len(nodeList) > 1:
buildPointers(i, nodeList[x+1], nodeList[1:])
else:
newNode = parent.addNode(info)
parent.numPointers = parent.numPointers + 1
if len(nodeList) > 1:
buildPointers(newNode, nodeList[x+1], nodeList[1:])
Essentially, I've removed the While loop and passed slices of the 1st element of nodeList if it has more than 1 item in it.

Django: Refer to previous item in model.save() method fails

I'm trying to implement a waiting room for items with queue verification.
The general idea is to put item to waiting room if, calculate it's counter (value defining how many new items are needed to confirm this one), decrease it after adding every new item and finally confirm it after decreasing counter below zero. If there're already items in waiting room, the calculated counter is increased by the counter of previous item so items are in queue.
My implementation is very simple, but I found this solution quite fast.
But referring to previous item is not working for me and I can't find the reason - it often returns 'random' (or at least not last one) value from Waiting objects.
Here's vital code snippet:
class Waiting(models.Model):
item = models.ForeignKey(Item)
counter = models.FloatField(default=0)
(...)
def clearup(self):
(...) #here is decrementing and confirming part - it's working fine
def save(self, update=False):
if update:
return super(Waiting, self).save()
item = self.item
self.clearup()
(...) #nothing important
self.counter = item.quantity * items_list[item.name][1]
last = Waiting.objects.exclude(
item__name="Something I don't want here").order_by('-pk')
if last:
last = last[0]
weight = items_list[last.item.name][1]
self.counter += (last.item.quantity * weight)
super(Waiting, self).save()
Edit: I'm retarded.
Like almost always - it was my fault.
I implemented vital part from another approach to this problem and this caused this issues.
Thanks for trying to help me anyway.

circular array class in python

I have a project to create a circular array class, and the language I will be using is python. I am new to classes in python, but after reading through some webpages and chapters in books I think I have an understanding of how they work. However I need help, so I figured I would come to the wonderful teachers here at SO :)
Our class must be able to implement several operations; insert at front, insert at back, insert at index, remove from front, remove from back, remove from index.
I have started coding but am running into some problems, and I am not 100% sure if my syntax is even right.
Here is what I have so far:
class circular:
def __init__(self):
self.store = []
self.capacity = len(self.store)
self.size = 0
self.startIndex = 0
self.endIndex = 0
def decrementIndex(self):
index = index - 1
if index < 0:
self.store = self.store + self.capacity
def incrementIndex(self):
index = index + 1
if index == self.capacity:
index = index - self.capacity
def addToBack(self, value):
self.store[self.endIndex] = value
self.endIndex = incrementIndex(self.endIndex)
self.size += 1
def addToFront(self, value):
if self.size == 0:
addToBack(self, value)
else:
self.startIndex = decrementIndex(self.startIndex)
self.store[self.startIndex] = value
self.size += 1
I stopped there to start testing some of the functions, primarily t he addTofront and addToback. Upon testing them in IDLE using c = circular() and c.addToBack(2) I get an index error...and I'm not sure why. That isn't the only problem, it's just where I have gotten stuck and need help moving forward.
I am posting here because I need help and want to learn, not because I am lazy and haven't tried researching my problem. Thanks already SO!
In __init__ you set
self.store = []
In addToBack you do
self.store[self.endIndex] = value
If this is the first operation on the circular array, and you pass 2 as the value, then that turns into
[][0] = 2
The problem should be obvious -- an empty list has no index of 0, it has no indexes at all.
You need to add the item to the list in a different way.
I'm not going to tell you exactly how as it's part of your homework to figure that out.

python list Index out of range error

I am working on a python tetris game that my proffessor assigned for the final project of a concepts of programming class. I have got just about everything he wanted to work on it at this point but I am having a slight problem with one part of it. Whenever I start moving pieces left and right I keep getting "index out of range error". This only happens when it is up against a piece. Here are the culprits that are giving me grief.
def clearRight(block=None):
global board, activeBlock, stackedBlocks
isClear = True
if(block == None):
block = activeBlock
if(block != None):
for square in block['squares']:
row = square[1]
col = square[0]+1
if(col >= 0 and stackedBlocks[row][col] !=None):
isClear=False
return isClear
def clearLeft(block=None):
global board, activeBlock, stackedBlocks
isClear = True
if(block == None):
block = activeBlock
if(block != None):
for square in block['squares']:
row = square[1]
col = square[0]-1
if(col >= 0 and stackedBlocks[row][col] !=None):
isClear=False
return isClear
I am not looking to get anyone to fix it for me, I'm only looking for tips on how to fix it myself. Thanks in advance for any help that is given.
There a typo that would cause that problem in the first method.
When you're checking each cell in the block shifted one right, you don't check if they are off the grid.
if (col >= 0 and ...)
probably should be
if (col < num_cols and ...)
I also agree with CrazyDrummer, make a generic clear function
Spoilers ...
def clear(x_offset, block=None):
if not block:
block = activeBlock
if not block: return True
for x,y in block:
x += x_offset
if not (0 <= x < num_cols) or stackedBlocks[x, y]:
return False
return True
Look at what's different when you're getting the exception. Try printing out program state information to help you zero in. There's only one place where you access an array with variable indexes, so you can narrow your search radius a bit.
Separate suggestion: Make a generic clear that takes determines what direction you want to clear from by the parameters.
I highly recommend the book debugging rules!, it will aid you in searching out and properly fixing problems. :D

Categories