Reputation: 67
I am currently practising python
on code wars, here is a prompt:
Create a Vector
object that supports addition, subtraction, dot products, and norms. So, for example:
a = Vector([1, 2, 3])
b = Vector([3, 4, 5])
c = Vector([5, 6, 7, 8])
a.add(b) # should return a new Vector([4, 6, 8])
a.subtract(b) # should return a new Vector([-2, -2, -2])
a.dot(b) # should return 1*3 + 2*4 + 3*5 = 26
a.norm() # should return sqrt(1^2 + 2^2 + 3^2) = sqrt(14)
a.add(c) # raises an exception
I have written functions add and subtract that pass some of the tests. However, I am running into issues with overwriting my previous list values of 'a' after running the add function. When I go into subtract, the 'a' values in the vector
are the summations computed from the previous instance of the add function.
I suspect its due to me running this line of code:
return self.__class__(self.list)
causing the instance of the class to overwrite itself.
Kindly please help, I believe I need to return a copy of the instance of the class but don't know how to do it.
class Vector:
def __init__(self, list):
self.list = list #[1,2]
self.copylist = list
def add(self,Vector):
try:
self.list = self.copylist
#take list from other vector
other = Vector.list
#take each value from other Vector and add it to self.list
for index,item in enumerate(Vector.list,0):
self.list[index] = item + self.list[index]
except:
print("Different size vectors")
#return the instance of a class
return self.__class__(self.list)
def subtract(self,Vector):
self.list = self.copylist
other = Vector.list
print(self.list)
print(other)
for index,item in enumerate(Vector.list,0):
self.list[index] = self.list[index] - item
return self.__class__(self.list)
def dot(self,Vector):
self.list = self.copylist
other = Vector.list
#print(self.list)
#print(other)
running_sum =0
for index,item in enumerate(Vector.list,0):
running_sum = running_sum + item * self.list[index]
#print(running_sum, " ", self.list[index], " ", item)
return running_sum
def norm(self):
running_sum = 0
for item in self.list:
running_sum += item**2
return running_sum ** 0.5
def toString(self):
return str(self.list)
`def equals(self,Vector):
return self.list == Vector.list
Here are some of the tests:
a = Vector([1, 2])
b = Vector([3, 4])
test.expect(a.add(b).equals(Vector([4, 6])))
a = Vector([1, 2, 3])
b = Vector([3, 4, 5])
test.expect(a.add(b).equals(Vector([4, 6, 8])))
test.expect(a.subtract(b).equals(Vector([-2, -2, -2]))) #code fails here
test.assert_equals(a.dot(b), 26)
test.assert_equals(a.norm(), 14 ** 0.5)
Upvotes: 2
Views: 1513
Reputation: 1
Please change function toString to str . its' already done.
class Vector :
def __init__(self , lst_vec):
self.lst_vec = lst_vec
def show_vector(self):
return self.lst_vec
def add(self , v ):
size_self = len(self.lst_vec)
size_v = len(v.lst_vec)
new_vector = []
if ( size_self != size_v ):
return Exception("error add")
else:
for i in range(size_self):
new_vector.append(self.lst_vec[i] + v.lst_vec[i])
return Vector(new_vector)
def subtract(self , v ):
size_self = len(self.lst_vec)
size_v = len(v.lst_vec)
new_vector = []
if ( size_self != size_v ):
return Exception("error subtract")
else:
for i in range(size_self):
new_vector.append(self.lst_vec[i] - v.lst_vec[i])
return Vector(new_vector)
def dot(self , v ):
size_self = len(self.lst_vec)
size_v = len(v.lst_vec)
new_vector = []
sum_vec = 0
if ( size_self != size_v ):
return Exception("Vector sizes are different")
else:
for i in range(size_self):
new_vector.append(self.lst_vec[i] * v.lst_vec[i])
for i in range(len(new_vector)):
sum_vec+=new_vector[i]
return sum_vec
def norm (self):
new_vec_sum = 0
for i in range(len(self.lst_vec)):
new_vec_sum +=( self.lst_vec[i] ) **2
return new_vec_sum ** 0.5
def toString(self):
str_self = '('
for i in range(len(self.lst_vec)):
str_self += str(self.lst_vec[i])
if i < (len(self.lst_vec)-1):
str_self+=','
else : pass
str_self+=')'
return str_self
def equals(self , v ):
return self.lst_vec == v.lst_vec
a = Vector([1,2,3])
b = Vector([3,4,5])
c = Vector([5,6,7,8])
print(a.add(b).show_vector())
print( a.add(b).equals(Vector([4,6,8])) )
print(a.subtract(b).show_vector())
print(a.dot(b))
print(a.norm())
print((a.toString() == '(1,2,3)'))
print(c.toString())
Upvotes: 0
Reputation: 23119
I think you're making this more complicated than it needs to be. You shouldn't be working with class objects at all. You should just be working with instances of the Vector class. Here's what I think your code should look like:
class Vector:
def __init__(self, initial_elements):
self.elements = list(initial_elements) # make a copy of the incoming list of elements
def add(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
# copy our elements
r = list(self.elements)
# add the elements from the second vector
for index, item in enumerate(other.elements, 0):
r[index] += item
# return a new vector object defined by the computed elements
return Vector(r)
def subtract(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
# copy our elements
r = list(self.elements)
# subtract the elements from the second vector
for index, item in enumerate(other.elements, 0):
r[index] -= item
# return a new vector object defined by the computed elements
return Vector(r)
def dot(self, other):
running_sum = 0
for index, item in enumerate(other.elements, 0):
running_sum += item * self.elements[index]
return running_sum
def norm(self):
running_sum = 0
for item in self.elements:
running_sum += item ** 2
return running_sum ** 0.5
def toString(self):
return str(self.elements)
def equals(self, other):
return self.elements == other.elements
def test():
a = Vector([1, 2])
b = Vector([3, 4])
print(a.add(b).equals(Vector([4, 6])))
a = Vector([1, 2, 3])
b = Vector([3, 4, 5])
print(a.add(b).equals(Vector([4, 6, 8])))
print(a.subtract(b).equals(Vector([-2, -2, -2])))
print(a.dot(b) == 26)
print(a.norm() == 14 ** 0.5)
test()
Result:
True
True
True
True
True
The general structure of your code is spot on.
One thing to note is that you shouldn't be using list
as a variable name, as it is a type name in Python. Also, you don't want to be passing around Vector
as a value. You want to be passing instances of Vector
and list
, with names that do not conflict with these type names.
My solution assumes you want Vector instances to be immutable, so each of your operations will return a new Vector object. You could also have them not be immutable and have, for example, the add
method just add the incoming vector into the target vector without creating a new object. I like keeping them immutable. I've been doing more and more of this "functional style" programming lately, where calls to object methods don't modify the target object (don't have side effects), but rather just return a new object.
I like your use of the test
class to do your testing. I chose to not deal with this, and just print the results of each test comparison to see that they all come out to True
. I'll leave it to you to restore your tests to using a test object with expect
and assert_equals
methods.
UPDATE: Here is a more compact way to write your add
and subtract
methods:
def add(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
return Vector([self.elements[i] + other.elements[i] for i in range(len(self.elements))])
def subtract(self, other):
# insure that the two vectors match in length
if len(self.elements) != len(other.elements):
raise Exception("Vector sizes are different")
return Vector([self.elements[i] - other.elements[i] for i in range(len(self.elements))])
Upvotes: 3
Reputation: 384
change:
return self.__class__(self.list)
to:
return self
although this would the same as,
return Vector(self.list)
if the class is more complicated it is better to return self
I think that's the issue, hope it helps :)
also, it is good practice to use different names. you used Vector for the class name as well as many of the inputs of the functions, you will run into problems when you do that.
Upvotes: 0