how to append 2 arrays using python classes - python

Im trying to append 2 arrays using python classes.
def __init__(self):
self.inArray = [0 for i in range(10)]
self.count = 0
def get(self, i):
return self.inArray[i]
def set(self, i, e):
self.inArray[i] = e
def length(self):
return self.count
def append(self, e):
self.inArray[self.count] = e
self.count += 1
if len(self.inArray) == self.count:
self._resizeUp() # resize array if reached capacity
def insert(self, i, e):
for j in range(self.count,i,-1):
self.inArray[j] = self.inArray[j-1]
self.inArray[i] = e
self.count += 1
if len(self.inArray) == self.count:
self._resizeUp() # resize array if reached capacity
def remove(self, i):
self.count -= 1
val = self.inArray[i]
for j in range(i,self.count):
self.inArray[j] = self.inArray[j+1]
return val
def __str__(self):
return str(self.inArray[:self.count])
def _resizeUp(self):
newArray = [0 for i in range(2*len(self.inArray))]
for j in range(len(self.inArray)):
newArray[j] = self.inArray[j]
self.inArray = newArray
def appendAll(self, A):
self.ls = [2,3,4,5]
ls = ls.append(A)
Im trying to write a function appendAll(self,A) that appends all elements of the array A in the array list (the one represented by self).
For example, if ls is [2,3,4,5] then ls.appendAll([42,24]) changes ls to [2,3,4,5,42,24].
This is all I can think of doing but I'm just stuck, any help will be appreciated

You can also just do like so (Basically just like extend).
ls += A
your code:
1. def appendAll(self, A):
2. self.ls = [2,3,4,5]
3. ls = ls.append(A)
The append function does not return a list
it operates on the original list.
the append function is also not what you are looking for,
because this will happen:
[2, 3, 4, 5, [42, 24]]
but extend will look like so:
[2, 3, 4, 5, 42,24]
Remember!
both functions do not return a new list
they simply operate on the given list.

You can use extend(
Have a look at What is the difference between Python's list methods append and extend? )
ls = ls.extend(A)
in your code :
def appendAll(self, A):
self.ls = [2,3,4,5]
self.ls = self.ls.extend(A)

Related

How to return a copy of an instance of a class?

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)
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))])
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.
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())

Python object1 = object2

I am writing a vector class in python (just to see if i can). i ran into a problem with the subtract method and i have no idea what could be causing this.
this is the class (i omitted "class Vector:").
def __init__(self, p):
print self
self.p = p
def __str__(self):
return str(list(self.p))
def equals(self, v):
if type(self) == type(v):
return str(self) == str(v)
return false
def size(self):
return len(self.p)
def add(self, v):
a = self.p
b = v.p
if self.size() == v.size():
for i in range(0, self.size()):
a[i] += b[i]
return Vector(a)
raise Exception()
def subtract(self, v):
a = self.p
b = v.p
if self.size() == v.size():
for i in range(0, self.size()):
a[i] -= b[i]
return Vector(a)
raise Exception()
def dot(self, v):
total = 0
if self.size() == v.size():
for i in range(0, len(self.p)):
total += self.p[i] * v.p[i]
return total
raise Exception()
def norm(self):
total = 1
if self.size() == v.size():
for i in range(0, len(self.p)):
total += self.p[i]^2
return total
raise Exception()
when i try to do:
a = Vector([1,1])
a.subtract(Vector[1,1])
print a
my thought says i should get [1,1] as output because i do not change any values of Vector a when i do the subtraction, i return a new vector with the values it should have. when i print the object it shows me that it is in a different space in memory but my output from 'print a' is [0,0]
also if i do
a = Vector(1,1)
b = a
a.subtract(Vector([1,1])
print a,b
my output is [0,0][0,0], what i want is [0,0][1,1]
why does b change with a ?
First question:
(1, 1) - (1, 1) == (0, 0)
The output of your program is correct. You change the values of a in your function with a[i] -= b[i] where a is the list of coordinates (not a copy of the list) in self and b the list of coordinates (again, not a copy) in v.
Second question:
b = a
a and b are now the same object (not different objects with the same value), so they change simultaneously.
Think of a and b as addresses for your computer.
a = Vector(1,1) # There is a Vector object somewhere in memory, e.g. 12345. Then a = 12345
b = a # b = a = 12345 (still the address of the same Vector object)
a.subtract(Vector([1,1])) # Change whatever is stored at the address of a = 12345
print a,b # both are still the address of the same object you modified in the previous step!

How to sum numbers from a linked list?

So for the following code I have been trying to use singly linked lists in python to calculate the sum of a list based on the even numbers within that list. I've written the code for the linked list portion I believe but I'm stumped on how to get it to actually take the even numbers only and sum them. Right now my code looks something like this:
def createList(plist):
linkedList = None
# goes backwards, adding each element to the beginning
# of the list.
for index in range(len(plist)-1, -1, -1):
linkedList = insertValueHead(linkedList, plist[index])
return linkedList
def sumEvens(linkedList): #This is what I'm looking for help with
.... #code
def testSumEvens():
myList = createList([14, 21, 29, 2, 16, 49, -26])
print "The sum of the even numbers in the first list is ", sumEvens(myList)
myList = createList([])
print "The sum of the even numbers in an empty list is ", sumEvens(myList)
myList = createList([5, 15, 25])
print "The sume of the even numbers in the final list is ", sumEvens(myList)
How would I go about making this create a sum of these lists? Such as in the first, 14 + 2 + 16?
As previously mentioned taking the modulous % of a number will yield the remainder. Thus if n%2 is 0, then the number is even. You could implement sumEvens like this...
def sumEvens(linkedList):
runningSum = 0
for number in linkedList:
if number % 2 == 0:
runningSum += number
print number
print runningSum
sumEvens([14, 21, 29, 2, 16, 49, -26]) # prints 6 (14+2+16-26)
here is a very basic linked list example
class LLNode:
def __init__(self,value):
self.next = None
self.val = value
def __float__(self):
return float(self.val)
def __int__(self):
return int(self.val)
def __str__(self):
return str(self.val)
class LL:
head =None
def iterNodes(self):
tmp = self.head
while tmp is not None:
yield tmp
tmp = tmp.next
def iterInts(self):
for node in self.iterNodes():
try:
yield int(node)
except ValueError:
pass
def iterFloats(self):
for node in self.iterNodes():
try:
yield float(node)
except ValueError:
pass
def iterStrings(self):
for node in self.iterNodes():
yield str(node)
def insert(self,value):
nn = LLNode(value)
if self.head is None:
self.head = nn
else:
list(self.iterNodes())[-1].next = nn
l = LL()
l.insert(1)
l.insert(2)
l.insert(3)
l.insert(4)
l.insert(5)
l.insert(6)
print "Sum of Even:",sum([n for n in l.iterInts() if n%2 == 0])
print "Sum of Odd:", sum([n for n in l.iterInts() if n%2 != 0])
the iterFunctions are the ones of primary interest to you I think

Generating 3 billion-th element of a sequence in python

I am trying to generate the following sequence:
011212201220200112 ... constructed as follows: first is 0,
then repeated the following action:
already written part is attributed to the right with replacement
0 to 1, 1 to 2, 2 to 0.
E.g.
0 -> 01 -> 0112 -> 01121220 -> ...
I am trying to find the 3 billion-th element of this sequence.
I realized that the sequence grows exponentially and hence derived that:
log(base2) (3 billion) ~ 32
So I just need to generate this sequence 32 times.
Here is what I tried in python:
import os
import sys
s=['0']
num_dict = {'0':'1' , '1':'2' , '2':'0'}
def mapper(b):
return num_dict[b]
def gen(s):
while True:
yield s
s.extend( map(mapper,s) )
a = gen(s)
for i in xrange(32):
a.next()
print a.next()[3000000000 - 1]
The problem is my RAM gets filled up before hitting the 3 billion mark.
Is there a better way to do this problem ?
EDIT: This program could crash your machine.Please try for xrange(25) for testing purposes
There are enough hints in the comments that you should be able to find the one-line solution. I think that it's more interesting to try to derive it with a more general tool, namely, implicit data structures. Here's a class for singleton lists.
class Singleton:
def __init__(self, x):
self.x = x
def __getitem__(self, i):
if not isinstance(i, int): raise TypeError(i)
elif not (0 <= i < len(self)): raise IndexError(i)
else: return self.x
def __len__(self): return 1
We can use this class like so.
>>> lst = Singleton(42)
>>> lst[0]
42
>>> len(lst)
1
Now we define a concatenation class and a mapper class, where the latter takes a function and implicitly applies it to each list element.
class Concatenation:
def __init__(self, lst1, lst2):
self.lst1 = lst1
self.lst2 = lst2
self.cachedlen = len(lst1) + len(lst2)
def __getitem__(self, i):
if not isinstance(i, int): raise TypeError(i)
elif not (0 <= i < len(self)): raise IndexError(i)
elif i < len(self.lst1): return self.lst1[i]
else: return self.lst2[i - len(self.lst1)]
def __len__(self): return self.cachedlen
class Mapper:
def __init__(self, f, lst):
self.f = f
self.lst = lst
def __getitem__(self, i): return self.f(self.lst[i])
def __len__(self): return len(self.lst)
Now let's rewrite your code to use these classes.
a = Singleton(0)
for i in range(32):
a = Concatenation(a, Mapper({0: 1, 1: 2, 2: 0}.get, a))
print(a[3000000000 - 1])
As an exercise: why do we need cachedlen?

Fixing array indices in Python

I'd like to have arrays that start from say an index of 4 and go to 9. I'm not interested in creating memory space for < 4, so how is best to proceed? My 2D code is as follows:
arr = [[ 0 for row in range(2)] for col in range(1, 129)]
>>> arr[0][0] = 1
>>> arr[128][0] = 1
Traceback (most recent call last):
File "<stdin>", line 1, in ?
IndexError: list index out of range
>>> arr[127][0] = 1
How can selectively just use the specific range i.e. where the last index runs from 1 to 128 inclusive not 0 to 127. This maybe obvious, but is there a way to do this?
Thanks for the suggestion for dicts, I have been avoiding these - I know - much of the code I'm converting is from C, but I think dictionaries might the saviour. Is there a way to do what I am asking with arrays?
For sparse arrays, use a dict:
sparseArray = {}
sparseArray[(0,0)] = 1
sparseArray[(128,128)] = 1
print sparseArray # Show the content of the sparse array
print sparseArray.keys() # Get all used indices.
You can simply emulate a list:
class OffsetList(object):
def __init__(self, offset=4):
self._offset = offset
self._lst = []
def __len__(self):
return len(self._lst)
def __getitem__(self, key):
return self._lst[key - self._offset]
def __setitem__(self, key, val):
self._lst[key - self._offset] = val
def __delitem__(self, key):
del self._lst[key - self._offset]
def __iter__(self):
return iter(self._lst)
def __contains__(self, item):
return item in self._lst
# All other methods go to the backing list.
def __getattr__(self, a):
return getattr(self._lst, a)
# Test it like this:
ol = OffsetList(4)
ol.append(2)
assert ol[4] == 2
assert len(ol) == 1
You have two options here. You can use sparse lists, or you can create a container type that basically has a normal list and a start index, such that when you request
specialist.get(4)
you actually get
specialist.innerlist[4 - startidx]
If you really wanted list semantics and all, I suppose you could do
class OffsetyList(list):
def __init__(self, *args, **kwargs):
list.__init__(self, *args)
self._offset = int(kwargs.get("offset", 0))
def __getitem__(self, idx):
return list.__getitem__(self, idx + self._offset)
def __setitem__(self, idx, value):
list.__setitem__(self, idx + self._offset, value)
# Implementing the rest of the class
# is left as an exercise for the reader.
ol = OffsetyList(offset = -5)
ol.extend(("foo", "bar", "baz"))
print ol[5], ol[7], ol[6]
but this seems very fragile to say the least.

Categories

Resources