Circular Queue Structure ( array-backed) - python

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) + "]"

Related

How to get Previous and Next element of a list in python

How can we get the previous and next item of a list in python? My code isn't working as it was supposed to. It always returns me 0th index of list. I dont want to use loop in this method.
Here's my code:
def provide_activetab_index(self,index):
if index > 0:
return index -1
if index < len(self.activetabs) - 1:
return index + 1
When i call this method it returns 0 when the self.current is 0.
def next(self):
index = self.provide_activetab_index(self.current+1)
self.display(self.frames[index])
def previous(self):
index = self.provide_activetab_index(self.current-1)
self.display(self.frames[index])
def next(self):
index = self.provide_activetab_index(self.current,1)
self.display(self.frames[index])
def previous(self):
index = self.provide_activetab_index(self.current,-1)
self.display(self.frames[index])
def provide_activetab_index(self,index,new):
if (index >= 0 and new == 1 and index < len(self.activetabs)-1) or (new == -1 and index > 0 and index < len(self.activetabs)):
return index + new
return index
EDIT
def provide_activetab_index(self,index,new):
l = len(self.activetabs)-1
if index >= l and new == 1:
return 0 # Return fist element if no last element
if index <= 0 and new == -1:
return l # Return last element if no previous element
else:
return index + new
To update self.current everytime
def next(self):
self.current = self.provide_activetab_index(self.current,1)
self.display(self.frames[self.current])
def previous(self):
self.current = self.provide_activetab_index(self.current,-1)
self.display(self.frames[self.current])
Hi i couldn't understand what you want exactly because there are few inputs that i don't know like self.current or self.activetabs so it is hard to modify your algorithm but there is data structure called "doubly_linked_list" you can implement that easily and than go to next or prev item with itemname.next or itemname.prev.Here is code
class Node:
def __init__(self, data, next_n=None, prev_n=None):
self.data = data
self.next = next_n
self.prev = prev_n
class Doubly_linked_list:
def __init__(self):
self.size = 0
self.root = None # points last member added
self.last = None # points first member added first member added is accepted as last member end next is None
def add(self, data):
if self.size == 0:
new_node = Node(data)
self.root = new_node
self.last = new_node
else:
new_node = Node(data)
new_node.next = self.root
self.root.prev = new_node
self.root = new_node
self.size += 1
def remove(self, data):
this_node = self.root
while this_node is not None:
if this_node.data == data:
if this_node.next is not None:
if this_node.prev is not None:
this_node.prev.next = this_node.next
this_node.next.prev = this_node.prev
else:
this_node.next.prev = None
self.root = this_node.next
else:
this_node.prev.next = None
self.last = this_node.prev
self.size -= 1
return True
else:
this_node = this_node.next
return False
def find_all(self, data):
this_node = self.root
while this_node is not None:
if this_node.data == data:
return data
elif this_node.next is None:
return False
else:
this_node = this_node.next
def print_all(self):
if self.root is None:
return None
this_node = self.root
print(this_node, end="-->")
while this_node.next != self.root:
this_node = this_node.next
print(this_node, end="-->")
print()
if you insist on finding nodes with indexes you can create a list object inside doubly_linked_list class inside init function self.list = [] and add all the nodes also to self.list and reach them by indexes.
With your code
def provide_activetab_index(self,index):
if index > 0:
return index -1
if index < len(self.activetabs) - 1:
return index + 1
when you pass index greater that 0 it will always return index-1.
As you mentioned self.current is 0 and you call it with
def next(self):
index = self.provide_activetab_index(self.current+1)
self.display(self.frames[index])
you actually calling
index = self.provide_activetab_index(1)
so this returns you 1-1 = 0

Problem breaking out of a generator while iterating through a for loop

Assigned to design a linked list class from scratch using a generator to iterate through the list, but I've had a problem debugging this issue:
class LinkedList:
def __init__(self, data = None):
self.node = Node(data)
self.first = self.node
self.last = self.node
self.n = 1
def append(self, data = None):
new = Node(data)
self.last.next = new
self.last = new
self.n += 1
def __iter__(self):
self.index = self.first
return self.generator()
def generator(self):
for i in range(0, self.n):
yield self.index
self.index = self.index.next
One of the tests that the current generator passes is:
for n in a:
print n
# which should and does output
0
1
2
However, it fails to output the proper values in this case
for n in a:
if n == 2:
break
else:
print n
# Outputs 0 1 2, instead of:
0
1
I think my understanding of generators is lacking, and would love any help you guys have to offer!
Your shouldn't use n == 2 as the break-condition.
Try this:
# Assume your defined class `Node.py` like this:
class Node:
def __init__(self, data=None):
self.val = data
self.next = None
# I didn't modify your `LinkedList.py`
class LinkedList:
def __init__(self, data=None):
self.node = Node(data)
self.first = self.node
self.last = self.node
self.n = 1
def append(self, data=None):
new = Node(data)
self.last.next = new
self.last = new
self.n += 1
def __iter__(self):
self.index = self.first
return self.generator()
def generator(self):
for i in range(0, self.n):
yield self.index
self.index = self.index.next
if __name__ == '__main__':
ass = LinkedList(0)
ass.append(1)
ass.append(2)
ass.append(3)
for n in ass:
if n.val == 2: # Notice here
break
else:
print(n.val) # And here

Min stack solution not working for leetcode

I'm trying a leetcode min stack problem and my code is not working, tried finding a solution but can't see what's wrong. It seems to work for most inputs but fails "
["MinStack","push","push","push","top","pop","getMin","pop","getMin","pop","push","top","getMin","push","top","getMin","pop","getMin"]
[[],[2147483646],[2147483646],[2147483647],[],[],[],[],[],[],[2147483647],[],[],[-2147483648],[],[],[],[]]" .
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.count = 0
self.minEle = -1
def push(self, x: int) -> None:
if self.count == 0:
self.minEle = x
self.stack.append(x)
elif x < self.minEle:
self.stack.append(2*x - self.minEle)
self.minEle = x
elif x >= self.minEle:
self.stack.append(x)
self.count += 1
def pop(self) -> None:
y = self.stack.pop()
if y < self.minEle:
self.minEle = 2*self.minEle - y
self.count -= 1
def top(self) -> int:
if self.count >=1:
return self.stack[(self.count - 1)]
else:
return 0
def getMin(self) -> int:
return self.minEle
Try:
class MinStack:
def __init__(self):
self.sc = []
self.sm = []
# #param x, an integer
# #return an integer
def push(self, x):
self.sc.append(x)
if x <= self.getMin():
self.sm.append(x)
return x
# #return nothing
def pop(self):
if self.sc.pop() == self.getMin():
self.sm.pop()
# #return an integer
def top(self):
return self.sc[-1]
# #return an integer
def getMin(self):
try:
return self.sm[-1]
except IndexError:
return self.top()
obj = MinStack()
obj.push(-2)
obj.push(0)
obj.push(-3)
print(obj.getMin())
obj.pop()
print(obj.top())
print(obj.getMin())
param_3 = obj.top()
param_4 = obj.getMin()

Iterative Towers of Hanoi using queue but the reverse function says it is not defined

class Node:
def __init__(self, value):
self.value = value
self.next = None
def __str__(self):
return "Node({})".format(self.value)
__repr__ = __str__
class Queue:
def __init__(self):
#Constructor take head and tail
self.head=None
self.tail=None
def __str__(self):
#proper format
temp=self.head
out=[]
while temp:
out.append(str(temp.value))
temp=temp.next
out=' '.join(out)
return ('Head:{}\nTail:{}\nQueue:{}'.format(self.head,self.tail,out))
__repr__=__str__
def isEmpty(self):
#check if the queue is empty
return (self.head == None)
def len(self):
#check the length of queue
current = self.head
len = 0
while current != None:
len += 1
current = current.next
return len
def enqueue(self, value):
#add a node to the end of queue
node = Node(value)
if self.isEmpty():
self.head = node
self.tail = node
else:
self.tail.next = node
self.tail = node
def dequeue(self):
#delete a node from the beginning of queue
if self.isEmpty():
return 'Queue is empty'
elif (self.head == self.tail):
pop = self.head.value
self.head = None
self.tail = None
return pop
else:
popped = self.head.value
self.head = self.head.next
return popped
def peek(self):
#show the first node
return self.head.value
class QueueTower:
def __init__(self, numDisks, A=Queue(), B=Queue(), C= Queue()):
self.numDisks = numDisks
self.A = Queue()
self.B = Queue()
self.C = Queue()
for i in (numDisks, 0, -1):
self.A.enqueue(i)
def reversequeue(q):
#reverse the queue without using stack
if q.isEmpty() == False:
data = q.peek()
q.dequeue()
q = reversequeue(q) #recurssion
q.enqueue(data)
return q
return Queue()
def validMove(self, a, b):
if not a.len():
c = reversequeue(b)
a.enqueue(c.dequeue())
elif not b.len():
d = reversequeue(a)
b.enqueue(d.dequeue())
elif int(a.peek()) > int(b.peek()):
e = reversequeue(b)
a.enqueue(e.dequeue())
else:
f = reversequeue(a)
b.enqueue(f.dequeue())
def hanoi(self, n):
if n%2 == 0:
self.B, self.C = self.C, self.B
move = 2**n
for i in range(1, move):
if i%3==1:
self.validMove(self.A, self.C)
if i%3==2:
self.validMove(self.A, self.B)
if i%3==0:
self.validMove(self.B, self.C)
print("rod " + str(self.A)+ " has " + str(self.A.len()), "rod B " + str(self.B.len()), "rod C "+ str(self.C.len()))
print("move needed is " + str(move-1))
tower1 = QueueTower(3)
tower1.hanoi(3)
I have tested to code for function reversequeue. It works fine for other example but I can't make it work for this. It returns that reversequeue is undefined. I put the function inside the class. Please help me understand the problem.
Should I put the function in class Queue. What should I do in this situation?
Thank you so much for helping.
You forgot your self:
class QueueTower:
def __init__(self, numDisks, A=Queue(), B=Queue(), C= Queue()):
self.numDisks = numDisks
self.A = Queue()
self.B = Queue()
self.C = Queue()
for i in (numDisks, 0, -1):
self.A.enqueue(i)
def reversequeue(self, q):
#reverse the queue without using stack
if q.isEmpty() == False:
data = q.peek()
q.dequeue()
q = self.reversequeue(q) #recurssion
q.enqueue(data)
return q
return Queue()
def validMove(self, a, b):
if not a.len():
c = self.reversequeue(b)
a.enqueue(c.dequeue())
# code continues

Remove Method Linked List

I am working on a doubly linked list and I can't get my remove function to work correctly. I want to return the value that it is being removed. I have tried various times, with no success. An extra pair of eye would be appreciated.
class DoublyLinked_List:
class __Node:
def __init__(self, val):
self.val = val
self.next = None
self.prev = None
def __init__(self):
self.__header = self.__Node(None)
self.__trailer = self.__Node(None)
self.__header.next = self.__trailer
self.__trailer.prev = self.__header
self.__size = 0
def __len__(self):
return self.__size
def remove_element_at(self, index):
if index > self.__size or index < 0 or index == self.__size:
raise IndexError
current = self.__header.next
if index == 0:
self.__header.next = self.__header.next.next
else:
for i in range(0, index-1):
current = current.next
current.next = current.next.next
self.__size -= 1
return current.val

Categories

Resources