Skip to content

Commit

Permalink
Fix #1 (implement stacks, queues, deques)
Browse files Browse the repository at this point in the history
Prompt Copilot with class name and doctest.
Generated code is wrong, uses undefined classes and methods,
implements methods that aren't in doctest.
Fix stack.py and keep it open as context for other classes.
Still subtle errors, like not updating a pointer.
  • Loading branch information
mwermelinger committed Dec 28, 2023
1 parent 1a0bc0f commit e5043bc
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 0 deletions.
121 changes: 121 additions & 0 deletions paddles/deque.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# A doubly-linked list node is a list [item, previous, next].
# These constants make the code more readable.
DATA = 0
PREV = 1
NEXT = 2


class LinkedListDeque:
"""Deque implementation using a doubly linked list for storage.
>>> items = LinkedListDeque("abc")
>>> print(items)
LinkedListDeque(['a', 'b', 'c'])
>>> items.size()
3
>>> items.take_front()
'a'
>>> items.take_back()
'c'
>>> items.front() == items.back() == 'b'
True
>>> items.add_back("C")
>>> items.add_front("A")
>>> print(items)
LinkedListDeque(['A', 'b', 'C'])
"""

def __init__(self, iterable=None):
"""Initialize this deque with the given items, if any."""
self._head = None
self._tail = None
self._length = 0
if iterable:
for item in iterable:
self.add_back(item)

def __str__(self):
"""Return a formatted string representation of this deque."""
strings = []
current = self._head
while current:
strings.append(f"'{current[DATA]}'")
current = current[NEXT]
return f"LinkedListDeque([{', '.join(strings)}])"

def size(self):
"""Return the number of items in this deque."""
return self._length

def add_front(self, item):
"""Insert the given item at the front of this deque."""
node = [item, None, None]
if self.size() == 0:
self._head = node
self._tail = node
else:
node[NEXT] = self._head
self._head = node
self._length += 1

def add_back(self, item):
"""Insert the given item at the back of this deque."""
node = [item, None, None]
if self.size() == 0:
self._head = node
self._tail = node
else:
node[PREV] = self._tail
self._tail[NEXT] = node
self._tail = node
self._length += 1

def take_front(self):
"""Remove and return the item at the front of this deque.
Raise ValueError if this deque is empty.
"""
if self.size() == 0:
raise ValueError("can't take from an empty deque")
item = self._head[DATA]
self._head = self._head[NEXT]
self._length -= 1
if self.size() == 0:
self._tail = None
else:
self._head[PREV] = None
return item

def take_back(self):
"""Remove and return the item at the back of this deque.
Raise ValueError if this deque is empty.
"""
if self.size() == 0:
raise ValueError("can't take from an empty deque")
item = self._tail[DATA]
self._tail = self._tail[PREV]
self._length -= 1
if self.size() == 0:
self._head = None
else:
self._tail[NEXT] = None
return item

def front(self):
"""Return the item at the front of this deque without removing it.
Raise ValueError if this deque is empty.
"""
if self.size() == 0:
raise ValueError("Deque is empty")
return self._head[DATA]

def back(self):
"""Return the item at the back of this deque without removing it.
Raise ValueError if this deque is empty.
"""
if self.size() == 0:
raise ValueError("Deque is empty")
return self._tail[DATA]
73 changes: 73 additions & 0 deletions paddles/queue.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# A linked list node is a list [item, next].
# These constants make the code more readable.
DATA = 0
NEXT = 1


class LinkedListQueue:
"""A queue implemented using a linked list.
>>> q = LinkedListQueue("abc")
>>> q.size()
3
>>> q.dequeue()
'a'
>>> q.front()
'b'
>>> q.enqueue("d")
>>> print(q)
LinkedListQueue(['b', 'c', 'd'])
"""

def __init__(self, iterable=None):
"""Initialize this queue with the given items, if any."""
self._head = None
self._tail = None
self._length = 0
if iterable:
for item in iterable:
self.enqueue(item)

def __str__(self):
"""Return a formatted string representation of this queue."""
strings = []
current = self._head
while current:
strings.append(f"'{current[DATA]}'")
current = current[NEXT]
return f"LinkedListQueue([{', '.join(strings)}])"

def size(self):
"""Return the number of items in this queue."""
return self._length

def enqueue(self, item):
"""Insert the given item at the back of this queue."""
node = [item, None]
if self.size() == 0:
self._head = node
self._tail = node
else:
self._tail[NEXT] = node
self._tail = node
self._length += 1

def front(self):
"""Return the item at the front of this queue without removing it."""
if self.size() == 0:
raise ValueError("can't access front of an empty queue")
return self._head[DATA]

def dequeue(self):
"""Remove and return the item at the front of this queue,
or raise ValueError if this queue is empty.
"""
if self.size() == 0:
raise ValueError("can't dequeue from an empty queue")
item = self._head[DATA]
self._head = self._head[NEXT]
self._length -= 1
if self.size() == 0:
self._tail = None
return item
126 changes: 126 additions & 0 deletions paddles/stack.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
class DynamicArrayStack:
"""A stack implementation using Python lists.
>>> stack = DynamicArrayStack("abc")
>>> stack.size()
3
>>> stack.pop()
'c'
>>> stack.peek()
'b'
>>> stack.push("C")
>>> print(stack)
DynamicArrayStack(['a', 'b', 'C'])
"""

def __init__(self, iterable=None):
"""Initialize this stack with the given items, if any."""
if iterable:
self._members = list(iterable)
else:
self._members = []

def __str__(self):
"""Return a string representation of this stack.
The string is 'DynamicArrayStack([bottom member, ..., top member])'.
"""
return f"DynamicArrayStack({self._members})"

def size(self):
"""Return how many members this stack has."""
return len(self._members)

def push(self, item):
"""Add the given item to the top of this stack."""
self._members.append(item)

def pop(self):
"""Remove and return the item on the top of this stack.
Raise ValueError if this stack is empty.
"""
if self.size() == 0:
raise ValueError("can't pop a member from an empty stack")
return self._members.pop()

def peek(self):
"""Return the item on the top of this stack.
Raise ValueError if this stack is empty.
"""
if self.size() == 0:
raise ValueError("can't peek top member of an empty stack")
return self._members[-1]


# Each linked list node is a tuple (data, next).
# These constants make the code more readable.
DATA = 0
NEXT = 1


class LinkedListStack:
"""A stack implementation using singly-linked lists.
>>> stack = LinkedListStack("abc")
>>> stack.size()
3
>>> stack.pop()
'c'
>>> stack.peek()
'b'
>>> stack.push("C")
>>> print(stack)
LinkedListStack(['a', 'b', 'C'])
"""

def __init__(self, iterable=None):
"""Initialize this stack with the given items, if any."""
self._head = None
self._length = 0
if iterable:
for item in iterable:
self.push(item)

def __str__(self):
"""Return a string representation of this stack.
The string is 'LinkedListStack([bottom member, ..., top member])'.
"""
strings = []
current = self._head
while current:
strings.append(f"'{current[DATA]}'")
current = current[NEXT]
return "LinkedListStack([" + ", ".join(reversed(strings)) + "])"

def size(self):
"""Return how many members this stack has."""
return self._length

def push(self, item):
"""Add the given item to the top of this stack."""
self._head = (item, self._head)
self._length += 1

def pop(self):
"""Remove and return the item on the top of this stack.
Raise ValueError if this stack is empty.
"""
if self.size() == 0:
raise ValueError("can't pop a member from an empty stack")
item = self._head[DATA]
self._head = self._head[NEXT]
self._length -= 1
return item

def peek(self):
"""Return the item on the top of this stack.
Raise ValueError if this stack is empty.
"""
if self.size() == 0:
raise ValueError("can't peek top member of an empty stack")
return self._head[DATA]

0 comments on commit e5043bc

Please sign in to comment.