Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions submissions/AQuaZar/data-structures/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Data Structures API

This application is my solution to practice part of data-structures task during Kottans-backend online course. [Link to the task.](https://github.com/kottans/backend/blob/master/tasks/data-structures.md)

Role of this API is to provide means of interaction with two types of data-structures: stack and linked list. Client can work with data stored on the server's memory. Application accepts two types of requests PUT to change data and GET to receive full view of data-structure. To transfer data from client to server JSON format has to be used as a payload to request, response from server passed as a string.

## Available Data Parameters

### Stack

| Name | Value | Description |
| ----------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| **PUT** |
| "data_type" | "stack" | Specifies that stack data-structure is used |
| "action" | "push", "pop" | Push - adds value specified in "Value" property on top of the stack, pop - removes value from top of the stack and returns it in body of response |
| "value" | alphanumeric value | Value that will be pushed to the stack |
| **GET** |
| "data_type" | "stack" | Specifies that stack data is shown |
| "action" | "show" | Full view of stack will be provided in body of server response |

### Linked List

| Name | Value | Description |
| ----------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **PUT** |
| "data_type" | "linked_list" | Specifies that data from linked-list structure is affected |
| "action" | "insert", "remove" | Insert - value specified in "Value" property inserted as a head of the list and will point to successor, remove - removes value from the list |
| "successor" | alphanumeric value | Optional parameter, if member of list is provided, value specified in "Value" property will be inserted before specified successor |
| "value" | alphanumeric value | Value that will be inserted to the linked list |
| **GET** |
| "data_type" | "linked_list" | Specifies that linked-list data is shown |
| "action" | "show" | Full view of list will be provided in body of server response |

## Examples

For requests will be used 'requests' python library and 'json' library to serialize data.

import requests
import json

url = "http://localhost:8000/"

data = {"data_type": "linked_list", "action": "insert", "value": "Jonathan"}
data = json.dumps(data)
r = requests.put(url, data)

In this example the PUT request is performed. As a result of request string _"Jonathan"_ will be _inserted_ in _linked list_ hold in local server memory.

To check state of our linked list we can use GET request:

data = {"data_type": "linked_list", "action": "show"}
data = json.dumps(data)
r = requests.get(url, data=data)
print(r.content)

To check the body of respond, 'content' field is used, as result we get:

> b'head -> Jonathan -> None'

In next example we will push values 1,2,3,4,5 to stack and pop last two

for i in range(1, 6):
data = {"data_type": "stack", "action": "push", "value": str(i)}
data = json.dumps(data)
r = requests.put(url, data=data)
for i in range(1, 3):
data = {"data_type": "stack", "action": "pop"}
data = json.dumps(data)
r = requests.put(url, data=data)
print(r.content)

Server responded with:

> b'5'

> b'4'

Another feature of linked list insertion is to specify successor of inserted node. For example we have such list structure:

> b'head -> Jonathan -> Joseph -> Jotaro -> None'

And we want to insert value "Joske" before "Jotaro", so that "Jotaro" will be successor of "Joske", we have to add optional property "successor" to data.

data = {"data_type": "linked_list", "action": "insert", "value": "Joske", "successor":"Jotaro"}
data = json.dumps(data)
r = requests.put(url, data)

As result we get:

> b'head -> Jonathan -> Joseph -> Joske -> Jotaro -> None'
66 changes: 66 additions & 0 deletions submissions/AQuaZar/data-structures/data_structure.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
class Stack:
def __init__(self, *args):
self.stack = list(args)

def show(self):
return str(self.stack)

def push(self, value):
self.stack.append(value)

def pop(self):
return self.stack.pop()


class Node:
def __init__(self, data):
self.data = data
self.next = None


class Linked_list:
def __init__(self, head=None):
self.head = head

def insert(self, data, successor=None):
if not successor or successor == self.head.data:
node = Node(data)
node.next = self.head
self.head = node
return True
current = self.head
while current:
if current.next.data == successor:
node = Node(data)
node.next = current.next
current.next = node
return True
current = current.next
# Successor not found
return False

def show(self):
current = self.head
output = "head ->"
while current:
output += f" {current.data} ->"
current = current.next
output += " None"
return output

def remove(self, data):
current = self.head
# if head element has to be removed
if current.data == data:
self.head = current.next
del current
return True
# if element in tail
while current.next:
if current.next.data == data:
current.next = current.next.next
return True
current = current.next
# Specified element not in a list
return False

28 changes: 28 additions & 0 deletions submissions/AQuaZar/data-structures/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import requests
import json

url = "http://localhost:8000/"

data = {"data_type": "linked_list", "action": "insert", "value": "Jotaro"}
data = json.dumps(data)
r = requests.put(url, data)
data = {"data_type": "linked_list", "action": "insert", "value": "Joseph"}
data = json.dumps(data)
r = requests.put(url, data)
data = {"data_type": "linked_list", "action": "insert", "value": "Jonathan"}
data = json.dumps(data)
r = requests.put(url, data)
data = {
"data_type": "linked_list",
"action": "insert",
"value": "Joske",
"successor": "Jotaro",
}
data = json.dumps(data)
r = requests.put(url, data)


data = {"data_type": "linked_list", "action": "show"}
data = json.dumps(data)
r = requests.get(url, data=data)
print(r.content)
105 changes: 105 additions & 0 deletions submissions/AQuaZar/data-structures/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import http.server
import socketserver
import json
from data_structure import Stack, Linked_list


PORT = 8000

myStack = Stack()
myList = Linked_list()


def ParseRequest(self):
if not self.headers["Content-Length"]:
SendResponse(self, 411, "No 'Content-Length' provided")
return
content_length = int(self.headers["Content-Length"])
request = json.loads(self.rfile.read(content_length).decode("UTF-8"))
return request


def SendResponse(self, responseCode, responsebody=None):
if responsebody:
self.send_response(responseCode)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write(bytes(responsebody, "UTF-8"))
else:
self.send_response(responseCode)
self.end_headers()
return


class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
request = ParseRequest(self)
if not request:
return

if "data_type" in request and "action" in request:
if request["data_type"] == "stack" and request["action"] == "show":
SendResponse(self, 200, myStack.show())
elif request["data_type"] == "linked_list" and request["action"] == "show":
SendResponse(self, 200, myList.show())
else:
SendResponse(
self, 400, "Wrong value for 'data_type' or 'action' properties"
)
else:
SendResponse(self, 400, "No 'data_type' or 'action' properties")

def do_PUT(self):
request = ParseRequest(self)
if not request:
return

if "data_type" in request and "action" in request:
if request["data_type"] == "stack":
if request["action"] == "push" and "value" in request:
if request["value"].isalnum():
myStack.push(request["value"])
SendResponse(self, 200)
else:
SendResponse(self, 400, "Value is not string or number")

elif request["action"] == "pop":
if len(myStack.stack) >= 1:
SendResponse(self, 200, myStack.pop())
else:
SendResponse(self, 409, "Can't pop from empty stack")
else:
SendResponse(self, 400, "Wrong 'action' value")

elif request["data_type"] == "linked_list":
if request["action"] == "insert" and "value" in request:
if request["value"].isalnum():
if "successor" in request:
try:
myList.insert(request["value"], request["successor"])
SendResponse(self, 200)
except:
SendResponse(self, 409, "Successor not found")
else:
myList.insert(request["value"])
SendResponse(self, 200)
else:
SendResponse(self, 400, "Value is not string or number")

elif request["action"] == "remove" and "value" in request:
try:
myList.remove(request["value"])
SendResponse(self, 200)
except:
SendResponse(self, 409, "Value not in list")
else:
SendResponse(self, 400, "Wrong 'action' value")
else:
SendResponse(self, 400, "Wrong 'data_type' value")
else:
SendResponse(self, 400, "No 'data_type' or 'action' in request")


with socketserver.TCPServer(("", PORT), SimpleHTTPRequestHandler) as httpd:
print("serving at port", PORT)
httpd.serve_forever()