From e5043bc2a6b7c5ecd6ed4708de419474d838ac00 Mon Sep 17 00:00:00 2001 From: Michel Wermelinger Date: Thu, 28 Dec 2023 10:07:14 +0000 Subject: [PATCH] Fix #1 (implement stacks, queues, deques) 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. --- paddles/deque.py | 121 +++++++++++++++++++++++++++++++++++++++++++++ paddles/queue.py | 73 +++++++++++++++++++++++++++ paddles/stack.py | 126 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+) create mode 100644 paddles/deque.py create mode 100644 paddles/queue.py create mode 100644 paddles/stack.py diff --git a/paddles/deque.py b/paddles/deque.py new file mode 100644 index 0000000..72c45f4 --- /dev/null +++ b/paddles/deque.py @@ -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] diff --git a/paddles/queue.py b/paddles/queue.py new file mode 100644 index 0000000..50dd58f --- /dev/null +++ b/paddles/queue.py @@ -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 diff --git a/paddles/stack.py b/paddles/stack.py new file mode 100644 index 0000000..936a911 --- /dev/null +++ b/paddles/stack.py @@ -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]