I am trying to get the MaxNum to be a property of the class Node, but I got "maximum recursion depth exceeded"
class Node:
def __init__(self, data=None):
if data is None:
data = []
self.data = data
#property
def MaxNum(self, nlist=None):
if nlist == None:
nlist = self.data
if len(nlist) == 1:
return nlist[0]
else:
mx = self.MaxNum(nlist[1:])
return mx if mx > nlist[0] else nlist[0]
#property
def MinNum(self):
mn = self.data[0]
for n in self.data:
if n <= mn:
mn = n
return mn
def main():
with open('random_numbers.csv', mode='r', encoding='utf-8-sig') as f:
lst = [int(x) for x in f.read().split(",")]
y = Node(lst)
print(y.MinNum)
print(y.MaxNum)
return
if __name__ == "__main__":
main()
The MaxNum function alone works well, but when i add the decorator generates error: "maximun recursion depth exceeded".
Related
After watching https://www.youtube.com/watch?v=zi0rHwfiX1Q I tried to port the example from C (implementation) and Erlang (testing) to Python and Hypothesis. Given this implementation (the rem function emulates %'s C behavior):
import math
def rem(x, y):
res = x % y
return int(math.copysign(res,x))
class Queue:
def __init__(self, capacity: int):
self.capacity = capacity + 1
self.data = [None] * self.capacity
self.inp = 0
self.outp = 0
def put(self, n: int):
self.data[self.inp] = n
self.inp = (self.inp + 1) % self.capacity
def get(self):
ans = self.data[self.outp]
self.outp = (self.outp + 1) % self.capacity
return ans
def size(self):
return rem((self.inp - self.outp), self.capacity)
and this test code
import unittest
from hypothesis.stateful import rule, precondition, RuleBasedStateMachine
from hypothesis.strategies import integers
from myqueue import Queue
class QueueMachine(RuleBasedStateMachine):
cap = 1
def __init__(self):
super().__init__()
self.queue = Queue(self.cap)
self.model = []
#rule(value=integers())
#precondition(lambda self: len(self.model) < self.cap)
def put(self, value):
self.queue.put(value)
self.model.append(value)
#rule()
def size(self):
expected = len(self.model)
actual = self.queue.size()
assert actual == expected
#rule()
#precondition(lambda self: self.model)
def get(self):
actual = self.queue.get()
expected = self.model[0]
self.model = self.model[1:]
assert actual == expected
TestQueue = QueueMachine.TestCase
if __name__ == "__main__":
unittest.main()
The actual question is how to use Hypothesis to also parametrize over QueueMachine.cap instead of setting it manually in the test class.
You can set self.queue in an initialize method rather than __init__, using a suitable integers strategy for the capacity.
The program below stalls at line:
m = MapH()
This is related with the function:
def next(self):
If redefined as (should be only two underscores):
def __next__(self):
Then, got error message:
instance has no next() method
When hitting the line:
for e in m:
The full code is below:
class MapEntryH:
def __init__(self, key, value):
self.key = key
self.value = value
class MapIteratorH:
def __init__(self,entryList):
self._myEntryList = entryList
self._currItem = 0
def __iter__(self):
return self
def __next__(self):
if self._currItem < len(self._myEntryList):
item = self._myEntryList[self._currItem]
self._currItem += 1
return item
else:
StopIteration
class MapH:
def __init__(self):
self._entryList = list()
def __len__(self):
return len(self._entryList)
def _findPosition(self,key):
for i in range(len(self)):
if self._entryList[i].key == key:
return i
return None
def __contains__(self,key):
ndx = self._findPosition(key)
return ndx is not None
def add(self,key,value):
ndx = self._findPosition(key)
if ndx is not None:
self._entryList[ndx].value = value
return False
else:
entry = MapEntryH(key,value)
self._entryList.append(entry)
return True
def valueOf(self, key):
ndx = self._findPosition(key)
assert ndx is not None, "Invalid map key"
return self._entryList[ndx].value
def remove(self,key):
ndx =self._findPosition(key)
assert ndx is not None,"Invalid map key"
self._entryList.pop(ndx)
def __iter__(self):
return MapIteratorH(self._entryList)
def test_Map():
m = MapH()
m.add(1,"arg")
m.add(2,"eeu")
m.add(3,"ale")
m.add(4,"sue")
m.add(5,"bra")
temp = m.remove(5)
m.add(5,"chl")
m.add(5,"bol")
temp = m.valueOf(5)
temp = m._findPosition(4)
for e in m:
print(e)
me = MapEntryH(1,"arg")
test_Map()
How do I support iteration like:
for e in m:
print(e)
Or containment like:
me = MapEntryH(1,"arg")
if me in m:
print me.value + " is on the map"
I've been trying the recursive approach but been stuck for too long. I cant tell if it's my BST code that's wrong or my recursion.
Regardless of how many elements I put in my tree I still get the value 2 from my height function.
class Treenode:
def __init__(self, value = None, rchild = None, lchild = None):
self.value = value
self.rchild = rchild
self.lchild = lchild
class bin_tree:
def __init__(self):
self.root = None
def put(self, x):
if self.root is None:
self.root = Treenode(x)
return True
if self.exists(x) == True:
return False
p = self.root
while True:
if x < p.value:
if p.lchild is None:
p.lchild = Treenode(x)
return True
else:
p = p.lchild
elif x > p.value:
if p.rchild is None:
p.rchild = Treenode(x)
return True
else:
p = p.rchild
return
def exists(self, x):
p = self.root
while True and p != None:
if p.value == x:
return True
elif p.value > x and p.lchild != None:
p = p.lchild
elif p.value < x and p.rchild != None:
p = p.rchild
else:
return False
def isempty(self):
return self.root == None
def height(self):
def gh(enrot):
if enrot == None:
return 0
else:
return 1 + max(gh(enrot.lchild), gh(enrot.rchild))
return gh(self.root)
Example code:
from Bintree import *
p = bin_tree()
x = input()
for word in x.split():
p.put(word)
a = input()
if p.exists(a) is True:
print('Exists!')
else:
print('Does not exist!')
print(p.isempty())
print(p.height())
The height method is fine. In your put method, you stop without actually adding the element, so the height doesn't actually grow beyond 2:
def put(self, x):
...
while True:
if x < p.value:
...
elif x > p.value:
if p.rchild is None:
...
else:
p = p.rchild
return
# ^^^^^^ This shouldn't be here.
I have an entire Deque Array class that looks like this:
from collections import deque
import ctypes
class dequeArray:
DEFAULT_CAPACITY = 10 #moderate capacity for all new queues
def __init__(self):
self.capacity = 5
capacity = self.capacity
self._data = self._make_array(self.capacity)
self._size = 0
self._front = 0
def __len__(self):
return self._size
def __getitem__(self, k): #Return element at index k
if not 0 <= k < self._size:
raise IndexError('invalid index')
return self._data[k]
def isEmpty(self):
if self._data == 0:
return False
else:
return True
def append(self, item): #add an element to the back of the queue
if self._size == self.capacity:
self._data.pop(0)
else:
avail = (self._front + self._size) % len(self._data)
self._data[avail] = item
self._size += 1
#def _resize(self, c):
#B = self._make_array(c)
#for k in range(self._size):
#B[k] = self._A[k]
#self._data = B
#self.capacity = capacity
def _make_array(self, c):
capacity = self.capacity
return (capacity * ctypes.py_object)()
def removeFirst(self):
if self._size == self.capacity:
self._data.pop(0)
else:
answer = self._data[self._front]
self._data[self._front] = None
self._front = (self._front + 1) % len(self._data)
self._size -= 1
print(answer)
def removeLast(self):
return self._data.popleft()
def __str__(self):
return str(self._data)
and when I try to print the deque in the main it prints out something like this,
<bound method dequeArray.__str__ of <__main__.dequeArray object at 0x1053aec88>>
when it should be printing the entire array. I think i need to use the str function and i tried adding
def __str__(self):
return str(self._data)
and that failed to give me the output. I also tried just
def __str__(self):
return str(d)
d being the deque array but I still am not having any success. How do I do i get it to print correctly?
you should call the str function of each element of the array that is not NULL, can be done with the following str function:
def __str__(self):
contents = ", ".join(map(str, self._data[:self._size]))
return "dequeArray[{}]".format(contents)
What I get when I try to q = dequeArray(); print(q) is <__main__.py_object_Array_5 object at 0x006188A0> which makes sense. If you want it list-like, use something like this (print uses __str__ method implicitly):
def __str__(self):
values = []
for i in range(5):
try:
values.append(self._data[i])
except ValueError: # since accessing ctypes array by index
# prior to assignment to this index raises
# the exception
values.append('NULL (never used)')
return repr(values)
Also, several things about the code:
from collections import deque
This import is never user and should be removed.
DEFAULT_CAPACITY = 10
is never used. Consider using it in the __init__:
def __init__(self, capacity=None):
self.capacity = capacity or self.DEFAULT_CAPACITY
This variable inside __init__ is never user and should be removed:
capacity = self.capacity
def _make_array(self, c):
capacity = self.capacity
return (capacity * ctypes.py_object)()
Though this is a valid code, you're doing it wrong unless you're absolutely required to do it in your assignment. Ctypes shouldn't be used like this, Python is a language with automated memory management. Just return [] would be fine. And yes, variable c is never used and should be removed from the signature.
if self._data == 0
In isEmpty always evaluates to False because you're comparing ctypes object with zero, and ctypes object is definitely not a zero.
I am struggling on how to work out how I pass arguments from a function so that I can populate a list in another function - my code is:
infinity = 1000000
invalid_node = -1
startNode = 0
#Values to assign to each node
class Node:
distFromSource = infinity
previous = invalid_node
visited = False
#read in all network nodes
def network():
f = open ('network.txt', 'r')
theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
print theNetwork
return theNetwork
#for each node assign default values
def populateNodeTable():
nodeTable = []
index = 0
f = open('network.txt', 'r')
for line in f:
node = map(int, line.split(','))
nodeTable.append(Node())
print "The previous node is " ,nodeTable[index].previous
print "The distance from source is " ,nodeTable[index].distFromSource
index +=1
nodeTable[startNode].distFromSource = 0
return nodeTable
#find the nearest neighbour to a particular node
def nearestNeighbour(currentNode, theNetwork):
nearestNeighbour = []
nodeIndex = 0
for node in nodeTable:
if node != 0 and currentNode.visited == false:
nearestNeighbour.append(nodeIndex)
nodeIndex +=1
return nearestNeighbour
currentNode = startNode
if __name__ == "__main__":
nodeTable = populateNodeTable()
theNetwork = network()
nearestNeighbour(currentNode, theNetwork)
So, I am trying to fill the nearestNeighbour list in my nearestNeighbour function with a list of nodes nearest to the other nodes. Now, the all the other functions work correctly, with all argument passing functioning as it should.
However, my nearestNeighbour function throws up this error message:
if node != 0 and
theNetwork[currentNode].visited ==
false: AttributeError: 'list' object
has no attribute 'visited'
(Apologies for the layout, haven't quite fathomed the use of the code quotes yet)
class Node(object):
def __init__(self, me, dists):
super(Node,self).__init__()
self.me = me
self.dists = dists
_inf = Network.INF
self.neighbors = sorted((i for i,dist in enumerate(self.dists) if i!=me and dist!=_inf), key=dists.__getitem__)
self.clear()
def clear(self):
self.dist = None
self.prev = None
def nearestNeighbor(self):
try:
return self.neighbors[0]
except IndexError:
return None
def __str__(self):
return "{0}: {1}".format(self.me, self.dists)
class Network(object):
INF = 10**6
#classmethod
def fromFile(cls, fname, delim=None):
with open(fname) as inf:
return cls([[int(dist) for dist in line.split(delim)] for line in inf])
def __init__(self, distArray):
super(Network,self).__init__()
self.nodes = [Node(me,dists) for me,dists in enumerate(distArray)]
def __str__(self):
return '\n'.join(self.nodes)
def floodFill(self, fromNode):
_nodes = self.nodes
for n in _nodes:
n.clear()
_nodes[fromNode].dist = 0
# left as an exercise ;-)
def distances(self):
return [n.dist for n in self.nodes]
def main():
nw = Network.fromFile('network.txt', delim=',')
print(nw)
nw.floodFill(fromNode=0)
print(nw.distances())
if __name__=="__main__":
main()
That's because theNetwork[currentNode] returns a list. In other words: theNetwork is a list of lists.
This is the line where it is done:
theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
theNetwork = [[int(node) for node in line.split(',')] for line in f.readlines()]
theNetwork is a list of lists. A list (theNetwork[currentNode]) doesn't have a visited attribute.
Perhaps you intended something like:
for line in f.readlines():
theNetwork.extend((int(node) for node in line.split(',')))