This is a big one and I apologize.
I am practicing to make my coding more modular.
We are tasked to create a Shipyard system.
There are Containers in the Shipyard and Packages in the Containers.
There is a LinkedList program provided that can be imported. I added it on the bottom.
IMPORTANT: I CANNOT ALTER THE SORTED LINKED LIST PROGRAM IN ANY WAY HENCE WHY I USE OVERLOADERS
I have another program which is non-modular. It is specifically made for the assignment at hand and it works for the most part.
Python 3.5
from SortedLList import *
class Shipyard:
def __init__(self):
self._container = SortedLList()
def add(self, owner, destination, weight):
"""
This function does:
1. Adds a container for a specific destination if doesn't exist.
2. Adds a package in a container given that the total weight
doesn't exceed 2000 lbs
3. If it does, it creates another container headed in the same
direction and then the package is inserted there instead.
"""
self._container.insert(Self.Container(destination))
class Container:
def __init__(self, destination):
self._package = SortedLList()
self._dest = destination
self._weight = 0
self._max = 2000
def add_pack(self, owner, destination, weight):
"""
This function adds the weight of the package to the total
container weight. And inserts a Package Singly Linked List
object inside the container.
"""
self._weight += weight
self._package.insert(Self.Package(destination))
def __lt__(self, other):
return self._dest < other._dest
def __ge__(self, other):
return self._dest >= other._dest
def __eq__(self, other):
return self._dest == other._dest
class Package:
def __init__(self, owner, destination, weight):
self._owner = owner
self._dest = destination
self._weight = weight
def __lt__(self, other):
return self._weight < other._weight
def __ge__(self, other):
return self._weight >= other._weight
def __eq__(self, other):
return self._weight == other._weight
class SortedLList :
class _Node :
def __init__(self, elem, next) :
self._elem = elem
self._next = next
def __init__(self) :
self._first = None
self._size = 0
def __len__(self) :
return self._size
def isEmpty(self) :
return len(self) == 0
def first(self):
return self._elem._first
def insert(self, val) :
if (self.isEmpty() or val <self._first._elem):
self._size+=1
self._first = self._Node(val,self._first)
tmpRef=self._first
while(tmpRef._next!=None and val>=tmpRef._next._elem):
tmpRef=tmpRef._next
if val==tmpRef._elem:
return
self._size+=1
tmpRef._next=self._Node(val,tmpRef._next)
return
def isPresent(self, elem) :
tmpRef=self._first
while(tmpRef!=None):
if tmpRef._elem==elem:
return True
tmpRef=tmpRef._next
return False
def delete(self, elem) :
if self.isEmpty() :
return
if elem == self._first._elem :
self._size -= 1
self._first = self._first._next
return
tmpRef = self._first
while (tmpRef._next != None and elem > tmpRef._next._elem) :
tmpRef = tmpRef._next
if tmpRef._next == None : return
if tmpRef._next._elem != elem : return
self._size -= 1
tmpRef._next = tmpRef._next._next
return
def traversePrint(self) :
tmpRef = self._first
while tmpRef != None :
print(tmpRef._elem)
tmpRef = tmpRef._next
class Empty(Exception) :
pass
I want to be able to use the methods in the SortedLList program to be able to display information that I have in the main program.
Is there any way around typing:
print(self._cont._first._elem._dest) or print(self._cont._first._elem._package._first._elem._owner) by using traversePrint() without altering the helper code?
You can inherit SortedLList in a new class and overload the methods you want.
class MySortedLList(SortedLList):
def traversePrint(self):
# Your custom implementation
and then using that instead of SortedLLIst, e.g:
class Shipyard:
def __init__(self):
self._container = MySortedLList()
However,, you asked if you can use the SortedLList.traversePrint to print information about your main program, presumable Shipyard. This probably doesn't make sense because you'd break encapsulation. SortedLList knows about its elements and can only know about Shipyard if you give it a reference to Shipyard. So rather let Shipyard tell you about itself.
Related
I successfully solved an algorithm question to serialize and deserialize binary tree.
class Codec:
def __init__(self):
self.i=0
def serialize(self, root):
store=[]
def preorder(node):
if not node:
store.append("N")
return
store.append(str(node.val))
preorder(node.left)
preorder(node.right)
preorder(root)
return ",".join(store)
# serialized data is passed here as "data" argument
def deserialize(self, data):
values=data.split(",")
def helper():
if values[self.i]=="N":
self.i+=1
return
root=TreeNode(int(values[self.i]))
self.i+=1
root.left=helper()
root.right=helper()
return root
return helper()
to solve the deserialize function, I created a top-level state variable self.i. Instead, I want to pass i to the helper function but I cannot figure it out. I tried to code like this with local variable:
def deserialize(self, data):
values=data.split(",")
def helper(i):
if values[i]=="N":
i+=1
return
root=TreeNode(int(values[i]))
i+=1
root.left=helper(i)
# i think issue is here.
# Because i is modified inside root.left=helper(i)
# so somehow I need to keep track of this modification
root.right=helper(i)
return root
return helper(0)
Instead of using an instance attribute (i), you could use a local variable i like you tried, but then not passing it as argument to helper, but referencing it as a nonlocal name. But I would not advise that. Instead create an iterator over the given values. Then you can call next on it to get the next value.
Once you got rid of the ugly instance attribute, you no longer need instances at all, and I wonder why you would need a class Codec at all. It you really want to keep it, then create those two functions as static methods as it doesn't make sense to ever need to create an instance of Codec:
Here is complete code with a run on a sample tree:
class TreeNode:
def __init__(self, val):
self.val = val
self.left = self.right = None
def add(self, val):
if val < self.val:
if self.left:
self.left.add(val)
else:
self.left = TreeNode(val)
else:
if self.right:
self.right.add(val)
else:
self.right = TreeNode(val)
def print(self, tab=""):
if self.right:
self.right.print(tab + " ")
print(tab, self.val)
if self.left:
self.left.print(tab + " ")
#staticmethod
def of(*values):
if values:
root = TreeNode(values[0])
for val in values[1:]:
root.add(val)
return root
class Codec:
#staticmethod
def serialize(root):
store=[]
def preorder(node):
if not node:
store.append("N")
return
store.append(str(node.val))
preorder(node.left)
preorder(node.right)
preorder(root)
return ",".join(store)
#staticmethod
def deserialize(data):
values = iter(data.split(","))
def helper():
val = next(values)
if val=="N":
return
root = TreeNode(int(val))
root.left = helper()
root.right = helper()
return root
return helper()
tree = TreeNode.of(4,2,6,1,3,5,7)
tree.print()
s = Codec.serialize(tree)
print(s)
root = Codec.deserialize(s)
root.print()
I've created my Node and Stack classes, but I can't figure out how I can display the repr in the Stack class in order to be able to print all items currently in the stack? I've been trying to concatenate the nodes but I'm not sure how since the Stack() doesn't allow iterating through the way a list does?
The stack works as it should, I just don't know how to display it's contents?
Here is my code:
class Stack:
class Node:
def __init__(self, elem, next):
self.elem = elem
self.next = next
def __repr__(self):
return str(self.elem)
def __init__(self):
self._stack = None
self._size = 0
def __repr__(self):
# *Not sure how to implement this properly*
s = ''
for i in range(self._size):
last = self._stack.elem
s += (str(last))+ ', '
self._stack.elem = self._stack.next
return
def push(self, elem):
if self._stack == None:
self._stack = self.Node(elem, None)
self._size += 1
else:
self._stack = self.Node(elem, self._stack)
self._size += 1
def pop(self):
if self._stack == None:
raise Exception ('This Stack is empty!')
else:
last = self._stack.elem
self._stack = self._stack.next
self._size -= 1
return last
def top(self):
return self._stack.elem
def isEmpty(self):
return self._size == 0
Example:
s= Stack()
s.push(4)
s.push(9)
s.push("joe")
s
joe, 9, 9,
Thank you in advance.
A way simpler implementation that avoids all the problems and pitfalls of your solution:
from typing import Iterable, Any
class Stack:
def __init__(self, xs: Iterable = None):
self._items = [] if xs is None else list(xs)
def push(self, elem: Any):
self._items.append(elem)
def pop(self) -> Any:
return self._items.pop()
def top(self) -> Any:
return self._items[-1]
def isEmpty(self) -> bool:
return not self._items
def __repr__(self) -> str:
typename = type(self).__name__
return f'{typename}({self._items})'
def __str__(self) -> str:
return ', '.join(str(x) for x in self._items)
s = Stack()
s.push(4)
s.push(9)
s.push("joe")
print(s)
print(repr(s))
But note that there's little use to a class like this over just using a list like a stack to begin with.
The output:
4, 9, joe
Stack([4, 9, 'joe'])
Note that this has the top element at the end, you could reverse it if you like of course.
If you insist on a working __repr__ for your specific implementation, using __repr__ as you intend in a non-standard way, something like this would work:
def __repr__(self):
p = self._stack
elems = []
while p is not None:
elems.append(p.elem)
p = p.next
return ', '.join(elems)
But note that there's several other issues with your implementation, other than this not being a correct __repr__, as previously pointed out here and in the comments. Your 'node' has a __repr__ which just returns its element value (which isn't a valid representation at all in most cases); you seem to be using __repr__ where you're really after __str__.
If this were an assignment in programming class, I'm not sure I'd award a passing grade, depending on what the aim was.
I am trying to implement Singly Linked List in Python. This is my _Node class:
#!/usr/bin/env python3
class _Node:
"""Node class to create new nodes"""
def __init__(self, data=None, next=None):
"""Construction of node"""
self._data = data
self._next = next
I have removed push(), pop() and other methods from this code sample. They all are working.
class LinkedList:
"""Singly Linked List implementation for storage"""
def __init__(self):
"""Construction of Linked List"""
self._head = None
self._size = 0
def __len__(self):
"""Return length of linked list."""
self._count = 0
self._current = self._head
while self._current:
self._count += 1
self._current = self._current._next
return self._count
def value_at(self, index):
"""Return Value at given index"""
self._current = self._head
self._index = index
count = ans = 0
while count<= self._index:
if self._current == None:
return "List is empty."
ans = self._current._data
self._current = self._current._next
count += 1
return ans
def value_n_from_end(self, n):
"""Get value of nth element starting from end"""
self.n=n
self.n = int(self.__len__() - self.n -1)
print(self.n) #print value as expected
self.value_at(self.n)
Now my problem is that i can get value from value_at() but unable to get value from value_n_from_end() outside the class.
Input:-
l = LinkedList()
print(l)
print(l.__len__())
print(l.value_at(1))
print(l.value_n_from_end(2))
Output:-
5-> 3-> 4-> 6-> //My Linked List
4 //Length of linked list
3 //Value return by l.value_at(1)
1 //This is the value which i want to pass in self.value_at(self.n)
None //This is returned from (l.value_n_from_end(2))
Value of l.value_n_from_end(2) should be same as l.value_at(1) i.e. 3. But i am missing something.
The value_n_from_end does not return anything. You should write:
return self.value_at(self.n)
Indeed, self.value_at(self.n) returns what you want in the function value_n_from_end but then you have to get it back to you by using a return statement. Otherwise it is bound to the function namespace.
for my assignment I'm supposed to make a deque class that lets people insert from the front and the back, and also be able to remove from both the front and back, those are 4 separate functions in the Deque class.
If I use insert_front, then I can remove everything from the queue using remove_front, but if I use insert_front and try to use remove_rear, then my program breaks after doing remove_rear one time, it will remove the rear, but if I try to remove the next rear, the program breaks because there it doesn't know what the next rear node is, I have no idea how to be able to track both the front and rear so I can use these functions interchangeably. This also happens vice versa, with insert_rear and remove_front.
my code for the Deque class is as follows:
def insert_front( self, value ):
if self._rear==None and len(self)==1:
node = _DequeNode(value, self._front,self._rear)
self._front = node
self._rear=node
else:
node = _DequeNode(value, self._front,self._rear)
self._front = node
self._size += 1
return
def insert_rear( self, value ):
node = _DequeNode(value, self._front,self._rear)
self._rear = node
if self._front==None and len(self)==2:
self._front=node
self._size += 1
return
def remove_front( self ):
if self.is_empty():
value = None
else:
current = self._front
value = current._value
self._front = current._next
self._size -= 1
return value
def remove_rear( self ):
if self.is_empty():
value = None
else:
current = self._rear
value = current._value
self._rear = current._prev
self._size -= 1
return value
and this is my _DequeNode class:
def __init__(self, value, next_node,prev_node):
self._value = copy.deepcopy(value)
self._next = next_node
self._prev = prev_node
return
I definitely did something wrong while altering the code, because this was originally for a linked list, where you can only remove and insert from the front, and the teacher asked us to make it into a Deque that has both front and rear, I edited the code based on what I thought was supposed to happen..
Can someone please help me with this? I've been trying to figure this out for the entire day!
Thanks in advance!!
Here is a working version I wrote up real quick.
Also I added a __repr__ method so you could see what's happening (this isn't actually a good practice for a __repr__ unless you also modify the __init__ to be capable of taking the output as an argument.
You may also want to take a look at https://github.com/python-mirror/python/blob/master/Modules/_collectionsmodule.c - which contains the python deque implementation.
class DQ:
def __init__(self):
self._front = self._rear = None
self._size = 0
def insert_front( self, value ):
self._front = DequeNode(value, prev=self.front)
if self.size > 0:
self.front.prev._next = self._front
else:
self._rear = self._front
self._size += 1
def insert_rear( self, value ):
self._rear = DequeNode(value, next=self.rear)
if self.size > 0:
self.rear.next._prev = self._rear
else:
self._front = self._rear
self._size += 1
def pop_front( self ):
if self.empty:
raise IndexError("deque is empty")
else:
ret = self._front
self._size -= 1
self._front = self._front.prev
if self.front:
self.front._next = None
if self.size == 0:
self._front = None
return ret
def pop_rear( self ):
if self.empty:
raise IndexError("deque is empty")
else:
ret = self._rear
self._size -= 1
self._rear = self._rear.next
if self.rear:
self.rear._prev = None
if self.size == 0:
self._front = None
return ret
#property
def empty(self):
return self._size == 0
#property
def size(self):
return self._size
#property
def front(self):
return self._front
#property
def rear(self):
return self._rear
def __str__(self):
cur = self.rear
l = []
for i in range(self.size):
l.append(cur)
cur = cur.next
return str(l)
def __repr__(self):
return self.__str__()
class DequeNode:
def __init__(self, value=None, next=None, prev=None):
self._value = value
self._next =next
self._prev = prev
#property
def prev(self):
return self._prev
#property
def next(self):
return self._next
def __str__(self):
return str(self._value)
def __repr__(self):
return str("DequeNode( %s )" %self._value)
I am trying to solve this problem:
Imagine a (literal) stack of plates. If the stack gets too high, it
might topple. There- fore, in real life, we would likely start a new
stack when the previous stack exceeds some threshold. Implement a data
structure SetOfStacks that mimics this. SetOf- Stacks should be
composed of several stacks, and should create a new stack once the
previous one exceeds capacity. SetOfStacks.push() and
SetOfStacks.pop() should behave identically to a single stack (that
is, pop() should return the same values as it would if there were just
a single stack). Bonus: Implement a function popAt(int index) which
performs a pop operation on a specific sub-stack.
So I wrote the code:
#!/bin/env python
from types import *
class Stack:
def __init__(self):
self.items = []
self.capacity = 3
self.stackscount = 0
def create(self):
id = self.stackscount + 1
id = str(id) + "_stack"
# How to create a new instance of Stack class at runtime ?
# the __init__ must be run too.
def push(self, item):
if self.size() <= self.capacity:
self.items.append(item)
else:
self.create()
def pop(self):
return self.items.pop()
def popAt(self):
pass
def peek(self):
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
s = Stack()
s.push(10)
How do I create a new s type object dynamically at runtime? I searched on the internet and found that using new.instance or new.classobj is the solution but when I did so my new object did not seem to have items from __init__ function. In python3, type() seems to be the answer but the docs doesn't have any examples.
You've confused yourself by referring to a "type object". In Python that means the class itself, not its instances.
To create new Stack objects, simply do what you're already doing: call the Stack class. You can append them to a list:
stacks = [Stack() for _ in range(5)]
However, as jon points out, that won't solve your problem since you haven't defined the SetOfStacks class.
You could simply use a parent-child relation : when a Stack is full, it creates a child and delegate next pushes to it. It could lead to :
class Stack:
def __init__(self, parent = None, id=None):
self.stackscount = 0
self.capacity = 3
self.items = []
self.parent = parent
self.id = id
self.child = None
def create(self):
id = self.stackscount + 1
id = str(id) + "_stack"
return Stack(self, id)
def push(self, item):
if self.size() <= self.capacity:
self.items.append(item)
else:
if self.child is None:
self.child = self.create()
self.child.push(item)
def pop(self):
if self.child is not None:
item = self.child.pop()
if len(self.child.items) == 0:
self.child = None
else:
item = self.items.pop()
return item
def popAt(self):
pass
def peek(self):
if self.child is not None:
item = self.child.peek()
else:
item = self.items[len(self.items)-1]
return item
def size(self):
l = len(self.items)
if self.child is not None:
l += self.child.size()
return l
s = Stack()
s.push(10)
popAt is still to be implemented, but I tested it and it correctly creates new stacks when pushing and empties and removes them when popping.
The implementation of popAt will require some evolutions to current pop implementation, to allow removing an intermediate stack :
def pop(self):
if self.child is not None:
item = self.child.pop()
if len(self.child.items) == 0:
self.child = self.child.child
if self.child is not None:
self.child.parent = self
else:
item = self.items.pop()
return item
def popAt(self, stacknumber):
s = self
for i in range(stacknumber):
s = s.child
if s is None:
return None
if len(s.items) == 0:
return None
item = s.items.pop()
if len(s.items) == 0 and s.parent is not None:
s.parent.child = s.child
if s.child is not None:
s.child.parent = s.parent
return item
The type() function is indeed what you are looking for. Documentation can be found here: https://docs.python.org/2/library/functions.html#type
You can call it like this:
# Bases is a tuple of parent classes to inherit
bases = Stack,
# Dict contains extra properties for the class, for example if you want to add a class variable or function
dict_ = {}
# Construct the class
YourClass = type('YourClass', bases, dict_)
# Create an instance of the class
your_instance = YourClass()
It looks like you are just looking at instance creation though:
class Stack(object):
def create(self):
id = self.stackscount + 1
id = str(id) + "_stack"
# How to create a new instance of Stack class at runtime ?
# the __init__ must be run too.
stack = Stack()