From efe427bea8860914c6707977756dbbe4b1f8e3b6 Mon Sep 17 00:00:00 2001 From: Mazzart Date: Sun, 19 Apr 2020 22:54:06 +0300 Subject: [PATCH] Add linked_list and stack implementations. Add base server to handle http requests --- submissions/mazzart/data-structures/app.py | 84 +++++++++++++++++++ .../mazzart/data-structures/linked_list.py | 73 ++++++++++++++++ submissions/mazzart/data-structures/stack.py | 16 ++++ 3 files changed, 173 insertions(+) create mode 100644 submissions/mazzart/data-structures/app.py create mode 100644 submissions/mazzart/data-structures/linked_list.py create mode 100644 submissions/mazzart/data-structures/stack.py diff --git a/submissions/mazzart/data-structures/app.py b/submissions/mazzart/data-structures/app.py new file mode 100644 index 0000000..1383ae6 --- /dev/null +++ b/submissions/mazzart/data-structures/app.py @@ -0,0 +1,84 @@ +from http.server import BaseHTTPRequestHandler +from socketserver import TCPServer +from urllib.parse import urlparse + +from linked_list import LinkedList, Node +from stack import Stack + +PORT = 8000 + +linked_list = LinkedList() +stack = Stack() + + +class HTTPRequestHandler(BaseHTTPRequestHandler): + + def _set_headers(self): + self.send_response(200) + self.end_headers() + + def do_GET(self): + if self.path.replace('/', '') == 'list': + self._set_headers() + self.wfile.write(f'Show all: {linked_list}'.encode()) + + def do_POST(self): + parameters = urlparse(self.path) + if parameters.path.replace('/', '') == 'list': + items = parameters.query.split('&') + if len(items) == 1: + item = items[0].split('=')[1] + if isinstance(item, (int, float, str)): + try: + linked_list.insert(Node(item)) + self._set_headers() + self.wfile.write(f'Insert {item}'.encode()) + except Exception as error: + print(error) + elif len(items) == 2: + item, successor = items[0].split('=')[1], items[1].split('=')[1] + if isinstance(item, (int, float, str)): + try: + linked_list.insert(Node(item), successor) + self._set_headers() + self.wfile.write( + f'Insert {item} before {successor}'.encode()) + except Exception as error: + print(error) + elif parameters.path.replace('/', '') == 'stack': + item = parameters.query.split('=')[1] + if isinstance(item, (int, float, str)): + stack.push(item) + self._set_headers() + self.wfile.write(f'Push {item}'.encode()) + else: + self.send_response(400) + self.end_headers() + + def do_DELETE(self): + parameters = urlparse(self.path) + if parameters.path.replace('/', '') == 'list': + item = parameters.query.split('=')[1] + try: + response = linked_list.remove(item) + self._set_headers() + self.wfile.write(f'Remove {item}'.encode()) + except Exception as error: + print(error) + + elif parameters.path.replace('/', '') == 'stack': + response = stack.pop() + if response == 'Stack is empty': + self.send_response(204) + self.end_headers() + else: + self._set_headers() + self.wfile.write(f'Pop item: {response}'.encode()) + + +with TCPServer(("", PORT), HTTPRequestHandler) as httpd: + print("serving at port", PORT) + try: + httpd.serve_forever() + except KeyboardInterrupt: + print("\nserver stopped") diff --git a/submissions/mazzart/data-structures/linked_list.py b/submissions/mazzart/data-structures/linked_list.py new file mode 100644 index 0000000..e2235d1 --- /dev/null +++ b/submissions/mazzart/data-structures/linked_list.py @@ -0,0 +1,73 @@ +class LinkedList: + """ + Linked list is a collection of nodes where each node has two fields: + - data contains the value to be stored in the node + - next contains a reference to the next node on the list + + The first node is called the head and the last node must have its + next reference pointing to None. + """ + + def __init__(self): + self.head = None + + def insert(self, new_node, successor=None): + before_head = (self.head is not None and self.head.data == successor) + + if successor is None or before_head: + new_node.next = self.head + self.head = new_node + return + + if not self.head: + raise Exception('List is empty') + + previous_node = self.head + for node in self: + if node.data == successor: + previous_node.next = new_node + new_node.next = node + return + previous_node = node + + raise Exception("Node with data '%s' not found" % successor) + + def remove(self, node_to_remove): + if not self.head: + raise Exception('List is empty') + + if self.head.data == node_to_remove: + self.head = self.head.next + return + + previous_node = self.head + for node in self: + if node.data == node_to_remove: + previous_node.next = node.next + return + previous_node = node + + raise Exception("Node with data '%s' not found" % node_to_remove) + + def __iter__(self): + node = self.head + while node is not None: + yield node + node = node.next + + def __repr__(self): + node = self.head + nodes = [] + while node is not None: + nodes.append(node.data) + node = node.next + return ' - '.join(nodes) + + +class Node: + def __init__(self, data): + self.data = data + self.next = None + + def __repr__(self): + return self.data diff --git a/submissions/mazzart/data-structures/stack.py b/submissions/mazzart/data-structures/stack.py new file mode 100644 index 0000000..488e438 --- /dev/null +++ b/submissions/mazzart/data-structures/stack.py @@ -0,0 +1,16 @@ +class Stack: + """ + Stack is a data structure that stores items in LIFO manner + """ + + def __init__(self): + self.stack = [] + + def push(self, item): + self.stack.append(item) + + def pop(self): + try: + return self.stack.pop() + except IndexError: + return 'Stack is empty'