maybe a bit trivial question but i'm having trouble calling the object.
How can I call an object from this class and possibly call the add method correctly?
sample code:
class MyMatrix:
height = 0
width = 0
data = tuple()
def __init__(self, data):
self.height = len(data)
self.width = len(data[0])
self.data = data
def add(mat1, mat2):
if mat1.height != mat2.height or mat1.width != mat2.width:
print("The matrices are not the same size!")
return
rows = []
for i in range(len(mat1.data)):
row = []
for j in range(len(mat1.data[0])):
row.append(mat1[i][j] + mat2[i][j])
rows.append(tuple(row))
return MyMatrix(tuple(rows))
Thank you in advance for every answer.
You can call the methods like follows; for your code to work, however, you need to implement getitem (so that you can do matrix[1][2] e.g.).
class MyMatrix:
height = 0
width = 0
data = tuple()
def __init__(self, data):
self.height = len(data)
self.width = len(data[0])
self.data = data
def __getitem__(self, item):
return self.data.__getitem__(item)
def add(mat1, mat2):
if mat1.height != mat2.height or mat1.width != mat2.width:
print("The matrices are not the same size!")
return
rows = []
for i in range(len(mat1.data)):
row = []
for j in range(len(mat1.data[0])):
row.append(mat1[i][j] + mat2[i][j])
rows.append(tuple(row))
return MyMatrix(tuple(rows))
m1 = MyMatrix([[1,2,3]])
m2 = MyMatrix([[3,2,1]])
m12 = m1.add(m2)
print(m12.data)
Related
I have implemented this runningMax class:
class RunningMax():
def __init__(self,window):
self.window = window
self.values = deque()
self.maxima = deque()
return
def append(self,x):
self.values.append(x)
i = 0
while (len(self.maxima) > 0) and (x > self.maxima[-1]) and (i < min(len(self.values),self.window)):
# pop all values at back that are smaller than new value
self.maxima.pop()
i += 1
self.maxima.append(x)
return
def pop(self):
full = len(self.values) == self.window
if self.maxima[0]==self.values[0] and full:
# if a value is about to leave the sliding window, kick it from maxima
max = self.maxima.popleft()
else:
max = self.maxima[0]
if full:
self.values.popleft()
return max
def compute_max(a,window):
rm = RunningMax(window)
maxs = []
for i,ai in enumerate(a):
rm.append(ai)
maxs.append(rm.pop())
return maxs
The output of compute_max(a,window) compares exactly to:
pd.Series(a).rolling(window,min_periods=1).max()
So, its implemented correctly. Just would like to ask if there is any potential for improvement here? Anything that could be written more optimally basically.
Thanks!
I need to iterate over a list of points to compute the distance of a line. But I'm getting an attribute error from this code I created. I think it's because I overload the addition function. How do I fix this so that I can compute the distances and store it in the list?
I tried to replace dist = Line(i,i+1).distance with dist = Line(i[0],i[1]).distance but it would yield an indexing error and I would need a overload function for indexing but it was not stated in the instructions.
import math
class Point:
'''Class that creates points. Attributes: Eastings and Northings'''
def __init__(self,x,y):
self.eastings = x
self.northings = y
def getCoords(self):
self.coords = (self.eastings,self.northings)
return self.coords
def setCoords(self,other_x,other_y):
self.eastings = float(other_x)
self.northings = float(other_y)
def __str__(self):
return f"{self.eastings},{self.northings}"
def __add__(self,new_point):
return Line(self,new_point)
class Line(Point):
'''Class that creates line object based on two points'''
def __init__(self,start,end):
self.start = start
self.end = end
self.latitude = self.end.eastings - self.start.eastings
self.departure = self.end.northings - self.start.northings
self.distance = math.sqrt((self.latitude)**2 + (self.departure)**2)
self.azimuth = math.degrees(math.atan2(self.departure,self.latitude))
def __getitem__(self,index):
if index == 0:
ans = self.start
elif index == 1:
ans = self.end
else:
print("invalid index")
return ans
class Lot(Line):
def __init__(self,name,lstpoints):
self.name = name
self.corners = self.__setCorners(lstpoints)
self.lines = self.__getLines(lstpoints)
self.left = None
self.right = None
def __setCorners(self,lstpoints):
dct = {}
for k,val in enumerate(lstpoints):
new = {f"C{k+1}":val}
dct.update(new)
return dct
def __getLines(self,lstpoints):
lst_lines = []
lst_dist = []
for k,val in enumerate(lstpoints):
if k == len(lstpoints)-1:
break
else:
new = f"C{k+1}-C{k+2}"
lst_lines.append(new)
for i in lstpoints:
dist = Line(i,i+1).distance
dct_lines = dict(zip(lst_lines,lst_dis))
return dct_lines
#test code that yields the error
a = Point(0,0)
b = Point(1,1)
c = Point(1,0.5)
lot = Lot("A1",[a,b,c])
type(Lot)
The error:
AttributeError Traceback (most recent call last)
<ipython-input-78-8644b897c98b> in <module>()
2 b = Point(1,1)
3 c = Point(1,0.5)
----> 4 lot = Lot("A1",[a,b,c])
5 type(Lot)
<ipython-input-77-8492f1fa52db> in __init__(self, name, lstpoints)
3 self.name = name
4 self.corners = self.__setCorners(lstpoints)
----> 5 self.lines = self.__getLines(lstpoints)
6 self.left = None
7 self.right = None
<ipython-input-77-8492f1fa52db> in __getLines(self, lstpoints)
22 lst_lines.append(new)
23 for i in lstpoints:
---> 24 dist = Line(i,i+1).distance
25 dct_lines = dict(zip(lst_lines,lst_dis))
26 return dct_lines
<ipython-input-65-7ac5af0efeef> in __add__(self, new_point)
13 return f"{self.eastings},{self.northings}"
14 def __add__(self,new_point):
---> 15 return Line(self,new_point)
<ipython-input-72-7743a2ec7710> in __init__(self, start, end)
4 self.start = start
5 self.end = end
----> 6 self.latitude = self.end.eastings - self.start.eastings
7 self.departure = self.end.northings - self.start.northings
8 self.distance = math.sqrt((self.latitude)**2 + (self.departure)**2)
AttributeError: 'int' object has no attribute 'eastings'
try to replace these lines:
for i in lstpoints:
dist = Line(i,i+1).distance
by these:
for i in range(len(lstpoints)):
dist = Line(lstpoints[i],lstpoints[i+1]).distance
My question is pretty straightforward. Is there a library in Python that has a data structure that can represent items on a shelf? Essentially, it would need to be a matrix where each row is the same length but the items in each row can be of varying lengths.
Here's a visual representation:
This should tell you if two shelf items overlap on the shelves (in the sense that one is below or above the other).... Assuming you know where your shelf items are by index.
class Item(list):
pass
shelves = [
[Item([1, 2, 3, 4]) ,Item([5, 6 ])],
[Item([7, 8]),Item([9]),Item([10, 11]), Item([12])]
]
# shelf items are indexed by two indices, shelf and item
def shelf_items_overlap(shelves, shelf1, item1, shelf2, item2):
item1_real_index = sum(map(len, shelves[shelf1][:item1]))
item2_real_index = sum(map(len, shelves[shelf2][:item2]))
return range_overlaps(
item2_real_index, item2_real_index + len(shelves[shelf2][item2]),
item1_real_index, item1_real_index + len(shelves[shelf1][item1])
)
def range_overlaps(x11,x12,x21,x22):
''' return if (x11, x12) overlaps (x21, x22) '''
return x21<=x12<=x22 or x21<=x11<=x22 or x11<=x21<=x12 or x11<=x22<=x12
print(shelf_items_overlap(shelves, 0, 1, 1, 0), shelf_items_overlap(shelves, 0, 1, 1, 2))
I think your problem should make a better use of classes than arrays. I know that this maybe this is not the answer you're looking but here is a quick code of a class implementation of items and shelf_rows that gets you the info of what it is in a shelf.
class Item ():
# Init the item class with a lenght
def __init__(self, length, name = 'Item'):
self.name = name
self.length = length
# Allow us to use the len method on item to get the length
def __len__(self):
return self.length
# Show us a clear print of the Item
def __repr__(self):
return '%r of length (%r)' % (self.name,self.length)
class ShelfRow ():
#Make a ShelfRow of a fixed length
def __init__ (self, length):
self.length = length
self.space_left = length
self.items = []
#Use append like if it was a list
def append (self,Item):
if Item.length > self.space_left:
return 'This should throw an error because the length is too long for the space left'
else:
self.items.append (Item)
self.space_left = self.space_left - Item.length
# Use the __getitem__ special method to get the position of an item
def __getitem__(self,position):
return self.items[position]
#Print the content of items
def __repr__(self):
return '%r' % self.items
# Make three items
item_a = Item(4, 'Big Box')
item_b = Item(2, 'Medium Box')
item_c = Item(2, 'Medium Box')
item_d = Item(8, 'Super Big Box')
#Make a shelfRow
shelf_row1 = ShelfRow(8)
shelf_row2 = ShelfRow(8)
#Populate shelfs
shelf_row1.append(item_a)
shelf_row1.append(item_b)
shelf_row1.append(item_c)
shelf_row2.append(item_d)
#Make a shelf, it could be an object too (it should probably)
shelf = [shelf_row1,shelf_row2]
#Print what is in every shelf_row
for shelf_row in shelf:
print(shelf_row)
The other answer is probably the closest to what you want but I get the feeling that maybe you could do for something a little more abstract to solve your problem.
Anyways I hope that this was useful.
I am not aware of any module, but this seems like a traditional "Make this data structure" type of question. So here's a base you can work with, and it may seem similar to other questions, but this should work and satisfy your needs. Its pretty much an implementation that uses the idea used in page allocation as your problem can be seen as you need frame to contain a certain amount of pages of a fixed size. It could be optimized by using a better algorithm (or process to add) but I forgot which one I used is called nor did I feel like implementing something more complicated.
class Item:
def set_width(self, width):
self.width = width
def get_width(self):
return self.width
def __init__(self, width=0):
self.width = width
class Shelf:
def add_item(self, item):
if item.get_width() > self.max_width:
print("Item will not fit in the shelf.")
return False
row = 0
while (row < len(self.rows)):
if (self.get_row_tot(row) + item.get_width()) <= self.max_width:
self.rows[row].append(item)
return True
row += 1
# Stop here, we want to prevent addition of a shelf
if max_height != -1 and row >= max_height:
print("Item will not fit in the shelf.")
return False
self.rows.append([item])
return True
def get_row_tot(self, row):
tot = 0
for i in self.rows[row]:
tot += i.get_width()
return tot
def remove_item(self, row, item):
if row < len(self.rows):
self.rows[row].remove(item)
return True
else:
print("Row does not exist")
return False
def __init__(self, max_width, max_height=-1):
"""
max_height = -1 means no height limit
"""
self.max_width = max_width
self.max_height = max_height
self.rows = []
self.head = 0
a = Shelf(3)
b = Item(1)
c = Item(1)
d = Item(2)
e = Item(2)
a.add_item(b)
a.add_item(c)
a.add_item(d)
a.remove_item(0, c)
a.remove_item(2, e)
a.add_item(e)
Like I said, this could be optimized and some additions could be made such as a method to swap, set, search, sort and so on so forth. You can also modify Item to be an object you're working with.
I define arr = [] before anything else. Why do I get an error when my class references it?
arr = []
class BST:
key = 0
left = None
right = None
height = 0
index = 0
def __init__(self):
height = 0
def __str__(self):
return str(self.key)
def populate(self):
print("populating")
print(self.key)
if (self.left != None):
arr = arr + [self.left.populate()]
if (self.right != None):
arr = arr + [self.right.populate()]
return self.key
m1 = BST()
m1.key = 3
m2 = BST()
m2.key = 5
m1.left = m2
print(m1.left != None)
m3 = BST()
m3.key = 6
m2.left = m3
res = m1.populate()
print(res)
~/py/python bst.py
True
populating
3
Traceback (most recent call last):
File "bst.py", line 41, in <module>
res = m1.populate()
File "bst.py", line 22, in populate
arr = arr + [self.left.populate()]
UnboundLocalError: local variable 'arr' referenced before assignment
~/py/
Use global in the scope of function
arr = []
class BST:
key = 0
left = None
right = None
height = 0
index = 0
def __init__(self):
height = 0
def __str__(self):
return str(self.key)
def populate(self):
global arr
print("populating")
print(self.key)
if (self.left != None):
arr = arr + [self.left.populate()]
if (self.right != None):
arr = arr + [self.right.populate()]
return self.key
m1 = BST()
m1.key = 3
m2 = BST()
m2.key = 5
m1.left = m2
print(m1.left != None)
m3 = BST()
m3.key = 6
m2.left = m3
res = m1.populate()
print(res)
True
populating
3
populating
5
populating
6
3
You can import the main module, or make it global inside
arr = []
class BST:
key = 0
left = None
right = None
height = 0
index = 0
def __init__(self):
height = 0
def __str__(self):
return str(self.key)
def populate(self):
import __main__
print("populating")
print(self.key)
if (self.left != None):
__main__.arr = arr + [self.left.populate()]
if (self.right != None):
__main__.arr = arr + [self.right.populate()]
return self.key
m1 = BST()
m1.key = 3
m2 = BST()
m2.key = 5
m1.left = m2
print(m1.left != None)
m3 = BST()
m3.key = 6
m2.left = m3
res = m1.populate()
print(res)
True
populating
3
populating
5
populating
6
3
The reason is in these lines:
if (self.left != None):
arr = arr + [self.left.populate()]
if (self.right != None):
arr = arr + [self.right.populate()]
You think that the assignment to a global variable arr should be made. But the fact is, when Python compiles the body of the function def populate(), it decides that arr is a local
variable because it is assigned within the function. The generated bytecode reflects this
decision and will try to fetch arr from the local environment. Later, when the call m1.populate() is made, the body of populate() trying to fetch the value of local variable arr and discovers that arr is unbound.
Your code will work if you will try not to override arr but to extend it:
if (self.left != None):
arr.append(self.left.populate())
if (self.right != None):
arr.append(self.right.populate())
As python starter, trying to get help from smart people when encountered the problem. And that is now:
I got to compare items (Qt scene items) from one list among each other, and make separate groups of items which collides mutually.
Please help me with code :
class MainWin(QMainWindow):
def __init__(self):
super(MainWin, self).__init__()
self.Win()
self.L = self.buildAllWalls()
items = self.scene.items()
allGroups = groupItemsFromList(None, items)
self.paintGroups(allGroups)
print len(allGroups)
def paintGroups(self, groups):
for g in groups :
color = QColor(0, 0, 0)
# RANDOM COLOR
namcol = "#%s" % "".join([hex(randrange(0, 255))[2:] for i in range(3)])
color.setNamedColor(namcol)
while color.isValid() == False : # ERROR CHECK
namcol = "#%s" % "".join([hex(randrange(0, 255))[2:] for i in range(3)])
color.setNamedColor(namcol)
pen = QPen(color, 14, Qt.SolidLine)
for w in g :
w.setPen(pen)
def Win(self):
self.scene = QGraphicsScene()
self.sView = QGraphicsView(self.scene)
self.sView.setRenderHint(QPainter.Antialiasing)
self.sView.setAlignment( Qt.AlignLeft | Qt.AlignTop )
self.setCentralWidget(self.sView)
self.setGeometry(20, 380, 400, 300)
self.show()
def buildAllWalls(self):
data = self.wallCoordinates()
for p in range(len(data)) :
ptA = QPointF(data[p][0], data[p][1])
ptB = QPointF(data[p][2], data[p][3])
self.wall(ptA, ptB)
def wall(self, ptA, ptB):
pen = QPen(QColor(100, 100, 100), 14, Qt.SolidLine)
currL = self.scene.addLine(QLineF(ptA.x(), ptA.y(), ptB.x(), ptB.y()))
currL.setPen(pen)
return currL
#[50,75,325,75],
def wallCoordinates(self):
data = [[50,100,150,100],[175,200,125,200],[175,275,125,275],[175,275,175,200],
[150,150,150,100],[175,100,225,100],[250,100,325,100],[350,125,175,125],
[50,125,125,125],[125,175,125,125],[150,150,175,150],[175,150,175,200],
[50,150,100,150],[100,150,100,200],[100,200,125,200],[50,175,75,175],
[75,225,75,175],[75,225,125,225],[125,275,125,225]]
return data
def main():
app = QApplication(sys.argv)
ex = MainWin()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Here is how I would write this:
def groupItemsFromList(self, itemList):
tmp = itemList[:]
allGroups = []
while tmp:
it = tmp.pop(0)
currentGroup = [it]
# loop from back to front so we can remove items safely
for i in range(len(tmp)-1, -1, -1):
if it.collidesWithItem(tmp[i]):
currentGroup.append(tmp.pop(i))
allGroups.append(currentGroup)
return allGroups
For example:
class Test(object):
def __init__(self, key):
self.key = key
def collidesWithItem(self, other):
return isinstance(other, self.__class__) and self.key == other.key
def __repr__(self):
return '{0}({1})'.format(self.__class__.__name__, self.key)
example = [Test(1), Test(2), Test(1), Test(1), Test(3), Test(2), Test(3), Test(4)]
print groupItemsFromList(None, example)
Output:
[[Test(1), Test(1), Test(1)], [Test(2), Test(2)], [Test(3), Test(3)], [Test(4)]]
This makes the assumption that all items that collide with an item will also collide with each other.
edit: Sounds like the assumption was not valid, try the following (untested):
def groupItemsFromList(self, itemList):
tmp = itemList[:]
allGroups = []
while tmp:
it = tmp.pop(0)
currentGroup = [it]
i = len(tmp) - 1
while i >= 0:
if any(x.collidesWithItem(tmp[i]) for x in currentGroup):
currentGroup.append(tmp.pop(i))
i = len(tmp) - 1
else:
i -= 1
allGroups.append(currentGroup)
return allGroups
It looks like you could do this:
def groupItemsFromList(self, itemList):
"""
Make a list of lists, where each list is composed of the
items (excepting itself, of course) that an item collides with.
"""
return [
[item for item in itemList[:i] + itemList[i:] if item.collidesWithItem(x)]
for i, x in enumerate(itemList)
]
itemList[:i] + itemList[i:] is python idiom for "I want all elements of the original list except the i'th item."
Later: I see. You want something more like this:
def groupItemsFromList(self, itemList):
def collision_indexes(i, target):
return [i] + [j for j, item in enumerate(itemList[i + 1:], start=i + 1) if item.collidesWithItem(target)]
processed = set()
results = []
for i, target in enumerate(itemList):
if i not in processed:
indexes = collision_indexes(i, target)
processed.update(indexes)
results.append([itemList[j] for j in indexes])
return results
The only advantage here is that this is side-effect-free code. There is no mutation to the original data but only functions applied to the data and changes made to new, temporary data structures.