Strange bevahiour of Python when adding up all elements in a matrix - python

I have an empty matrix in Python 2.7:
self.board = {}
N = 2
for i in range(N):
for j in range(N):
self.board[i, j] = 0
Now I want to add up all elements of the matrix. So I googled how to do it:
print sum(map(sum, self.board))
How would I sum a multi-dimensional array in the most succinct python?
Suprisingly, it prints out 4 - the sum of all indexes. Why is that? How can I sum the elements correctly?

Related

Combinations with un-fixed choices

I just started using Python for this project I was working on. I created a List of lists of lists of integers.
Ex. [[[0,1,2],[0,2,1]],[[0,1,2],[2,1,0]],[[0,1,2],[1,0,2]]]. I want to make all possible arrays that take one list from each list in the large list and map the integers to the corresponding columns on the 2d array. How can I do that without nested for loops? I would have used for loops for each list of lists, but the lengths of the list aren't fixed. The list follows this pattern.
list ((l[i])[(i-1)!])[i]
ex of final matrix.
[0 2 1]
[2 1 0]
[1 0 2]
This is the code I have so far:
k = (range(len(m)))
q = list(permutations(k))
p = list
for e in range(0, len(m)):
p.extend(q)
for j in range(0, len(m)):
if ((p[e])[j])[e] != e:
p[e].pop(j)
for z in range(0, len(m)):
Where m is the array I want to create (len(m) x len(m) array)
Thanks in advance.

Python randint() repeats numbers - seed is not the problem?

i do learn Python for scientific working. At the moment i try to generate a 10x10 random Matrix with binary entries: 0 and 1. I already got a solution with numpy BUT im interested of what is the error in my own solution.
The Idea is to Access every entry of my Matrix seperately and assign a value to it by calling random.randint(0, 1 ) within two while loops. In Advance i define a dummy 10x10 Matrix called "World" and reassign ist values it in the loop. The Code Looks how follows:
import random
World=list(10*[10*[0]]) #this is my dummy matrix
i=0
j=0
while i <= 9:
while j <= 9:
World[i][j]=random.randint(0, 1) #here i want to Access a specific element of my dummy Matrix and "overwrite" it
if j == 9:
j=0 #if the counter "j" reaches 9 - the last element - it shall assign j=0 and leave the innermost while loop by "break"
break
j=j+1
i=i+1
for x in World:
print(*x)
The Problem with the Output should be obvious:
columns are equal
I am hopefully u understand what was my Intention here and can help me fix my code. I tried many many Things but i did not fix this.
I already found a 2-line short solution which i will use in my final Code but i want to run this also on my own because i am convinced this could work also well.
Many Thanks in Advance.
- Wendel
Your error is in the creation of the list.
NOTE:
[0] * m returns just a reference to a list of m zeros, but not a list.
The subsequent repeating of this element creates a list of n items
that all reference to the same list (just as well as the operation b =
a for lists does not create the new list), so all rows in the
resulting list are actually the same string.
import random
#World=list(10*[10*[0]]) #this is my dummy matrix
n = 10
World= [0] * n
for i in range(n):
World[i] = [0] * n
i=0
j=0
while i <= 9:
while j <= 9:
World[i][j]=random.randint(0, 1) #here i want to Access a specific element of my dummy Matrix and "overwrite" it
if j == 9:
j=0 #if the counter "j" reaches 9 - the last element - it shall assign j=0 and leave the innermost while loop by "break"
break
j=j+1
i=i+1
for x in World:
print(*x)
Suppose that two numbers are given: the number of rows of n and the number of columns m. You must create a list of size n×m, filled with, say, zeros.
The obvious solution appears to be wrong:
a = [[0] * m] * n
This can be easily seen if you set the value of a[0][0] to 5, and then print the value of a[1][0] — it will also be equal to 5. The reason is, [0] * m returns just a reference to a list of m zeros, but not a list. The subsequent repeating of this element creates a list of n items that all reference to the same list (just as well as the operation b = a for lists does not create the new list), so all rows in the resulting list are actually the same string.
n = 3
m = 4
a = [[0] * m] * n
a[0][0] = 5
print(a[1][0])
A possible way: you can create a list of n elements (say, of n zeros) and then make each of the elements a link to another one-dimensional list of m elements:
n = 3
m = 4
a = [0] * n
for i in range(n):
a[i] = [0] * m
Another (but similar) way: create an empty list and then append a new element to it n times (this element should be a list of length m):
n = 3
m = 4
a = []
for i in range(n):
a.append([0] * m)
But the easiest way is to use generator, creating a list of n elements, each of which is a list of m zeros:
n = 3
m = 4
a = [[0] * m for i in range(n)]
In this case each element is created independently from the others. The list [0] * m is n times consructed as the new one, and no copying of references occurs.

Iterate over every black square of a "chessboard"

I'd like to iterate over every other element of a m-by-n "chessboard", i.e.,
l = []
for i in range(m):
for j in range(n):
if (i+j) % 2 == 0:
l.append(something(i, j))
I'm using an explicit loop here, but for speed would rather use a list comprehension.
Any hints?
For bonus points, the solution also works for i, j, k with (i+j+k) % 2 == 0.
Well, list comprehension is just like your nested for loop, except that this is done within the list brackets:
my_list = [something(i, j) for i in range(m) for j in range(n) if (i + j) % 2 == 0]
More generally, for n nested loops, you can use itertools.product, like this:
from itertools import product
my_list = [something(*p) for p in product(range(n), repeat=n) if sum(p) % 2 == 0]
As I understand it, you would like an explicit expression for the x and y coordinates of the black squares on the 'chess board', so that you don't have to evaluate the boolean for every square. Here is an implementation of my solution (for a 2-dimensional board):
import numpy as np
# 'Chess board' dimension
m = 3 # Number of columns
n = 4 # Number of rows
# Counter variable. The length of this array is equal to the total number of black squares.
k = np.arange(0,m*n,2)
x_coords = (k + (k/n) % 2) % n # x-coordinates of black squares
y_coords = (k + (k/n) % 2) / n # y-coordinates of black squares
print("x-coordinates: "+str(x_coords))
print("y-coordinates: "+str(y_coords))
For the 3x4 dimensional board in the example above, this generates the following output:
x-coordinates: [0 2 1 3 0 2]
y-coordinates: [0 0 1 1 2 2]
which you can verify by drawing a little diagram. Note that the 'helper variable' (k/n) % 2 keeps track of whether the row number is even or odd; the odd rows have an 'offset' with respect to the even ones.

Python 3: Multiply a vector by a matrix without NumPy

I'm fairly new to Python and trying to create a function to multiply a vector by a matrix (of any column size).
e.g.:
multiply([1,0,0,1,0,0], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]])
[1, 1]
Here is my code:
def multiply(v, G):
result = []
total = 0
for i in range(len(G)):
r = G[i]
for j in range(len(v)):
total += r[j] * v[j]
result.append(total)
return result
The problem is that when I try to select the first row of each column in the matrix (r[j]) the error 'list index out of range' is shown. Is there any other way of completing the multiplication without using NumPy?
The Numpythonic approach: (using numpy.dot in order to get the dot product of two matrices)
In [1]: import numpy as np
In [3]: np.dot([1,0,0,1,0,0], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]])
Out[3]: array([1, 1])
The Pythonic approach:
The length of your second for loop is len(v) and you attempt to indexing v based on that so you got index Error . As a more pythonic way you can use zip function to get the columns of a list then use starmap and mul within a list comprehension:
In [13]: first,second=[1,0,0,1,0,0], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]]
In [14]: from itertools import starmap
In [15]: from operator import mul
In [16]: [sum(starmap(mul, zip(first, col))) for col in zip(*second)]
Out[16]: [1, 1]
I think the problem with your code was that you loop through the rows of the matrix rather than by the columns. Also you don't reset your 'total' variable after each vector*matrix column calculation. This is what you want:
def multiply(v, G):
result = []
for i in range(len(G[0])): #this loops through columns of the matrix
total = 0
for j in range(len(v)): #this loops through vector coordinates & rows of matrix
total += v[j] * G[j][i]
result.append(total)
return result
i have attached a code for matrix multiplication do follow the example format for one dimensional multiplication (lists of list)
def MM(a,b):
c = []
for i in range(0,len(a)):
temp=[]
for j in range(0,len(b[0])):
s = 0
for k in range(0,len(a[0])):
s += a[i][k]*b[k][j]
temp.append(s)
c.append(temp)
return c
a=[[1,2]]
b=[[1],[2]]
print(MM(a,b))
result is [[5]]
r is an element from G so it's a row which only has two elements. That means you can't use index j to get a value from r because j goes from 0 till the length of v, which is 6 in your example.
I needed solution where the first matrix could be 2-dimensional. Extending the solution from #Kasramvd to accept a two dimensional first matrix. Posted here for reference:
>>> first,second=[[1,0,0,1,0,0],[0,1,1,1,0,0]], [[0,1],[1,1],[1,0],[1,0],[1,1],[0,1]]
>>> from itertools import starmap
>>> from operator import mul
>>> [[sum(starmap(mul, zip(row, col))) for col in zip(*second)] for row in first]
[[1, 1], [3, 1]]
# check matrices
A = [[1,2],[3,4]]
B = [[1,4],[5,6],[7,8],[9,6]]
def custom_mm(A,B):
if len(A[0]) == len(B): -- condition to check if matrix multiplication is valid or not. Making sure matrix is nXm and mXy
result = [] -- final matrix
for i in range(0,len(A)): -- loop through each row of first matrix
temp = [] -- temporary list to hold output of each row of the output matrix where number of elements will be column of second matrix
for j in range(0,len(B[0])): -- loop through each column of second matrix
total = 0
l = 0 -- dummy index to switch row of second matrix
for k in range(0,len(A[0])):
total += A[i][k]*B[l][j]
l = l+1
temp.append(total)
result.append(temp)
return result
else:
return (print("not possible"))
print(custom_mm(A,B))
There is a code that help u to multiply two matrix:
A=[[1,2,3],[4,5,6],[7,8,9]]
B=[[1,2,3],[4,5,6],[7,8,9]]
matrix=[]
def multiplicationLineColumn(line,column):
try:
sizeLine=len(line)
sizeColumn=len(column)
if(sizeLine!=sizeColumn):
raise ValueError("Exception")
res = sum([line[i] * column[i] for i in range(sizeLine)])
return res
except ValueError:
print("sould have the same len line & column")
def getColumn(matrix,numColumn):
size=len(matrix)
column= [matrix[i][numColumn] for i in range(size)]
return column
def getLine(matrix,numLine):
line = matrix[numLine]
return line
for i in range(len(A)):
matrix.append([])
for j in range(len(B)):
matrix[i].append(multiplicationLineColumn(getLine(A,i),getColumn(B,j)))
print(matrix)

Bi-dimensional arrays in Python

I have a vector with int values like:
v=[10,8,6]
and what I want is to create an m*m matrix that stores the distance between these elements, i.e. take each element of the vector and substract it from all the other ones, so at the end I will end up with:
m[3][3]=10-10 10-8 10-6
8-10 8-8 8-6
6-10 6-8 6-6
I want to implement it into Python, but without using NumPy. I have done this so far:
def main():
v=[10,8,6]
l=len(v)
m=[]
#filling the matrix
for i in range(0,l-1):
for j in range(0,l-1):
m[i][j]=abs(v[i]-v[j])
#visualize the matrix
for i in range(0,l-1):
for j in range(0,l-1):
print m[i][j]
But I am getting some error that does not recognize with the bounds of m. Why is that?
v= [10,8,6]
m = [[abs(y-x) for y in v] for x in v]
EDIT:
For pretty printing you can use something like:
for i in m:
print '%s '*len(i) % tuple(i)
You need to make a list for each row inside of the enveloping list. I used a double list comprehension to make m and then made the formatting a little prettier for printing out the matrix. Also, watch your indices: remember that range goes from the first index to one minus the second index passed to it. You could also do print ' '.join(row) for each row in m to print it out nicely.
def main():
v=[10,8,6]
l=len(v)
#filling the matrix
m=[[abs(x - y) for y in v] for x in v]
#visualize the matrix
for i in range(0,l):
for j in range(0,l):
print m[i][j],
print
main()
result:
0 2 4
2 0 2
4 2 0
Your list starts out empty. You can't index the element in the list. One way to solve this would be to create the lists and then append them.
m=[]
#filling the matrix
for i in range(0,l-1):
x = []
for j in range(0,l-1):
x.append( abs(v[i]-v[j]) )
m.append(x)
Or you could create the matrix and then fill it up
m=[[0] *l for x in range(l)]
#filling the matrix
for i in range(0,l-1):
for j in range(0,l-1):
m[i][j]=abs(v[i]-v[j])
better yet is the list comprehension other have shown
m = [[abs(y-x) for y in v] for x in v]
but then, I'd use numpy/scipy
m = scipy.spatial.distance.pdist(v)
You need to initialize each object in the first dimension as an array, otherwise it's like you're basically trying to index on None.
#filling the matrix
for i in range(0,l-1):
m[i] = []
for j in range(0,l-1):
m[i][j]=abs(v[i]-v[j])

Categories

Resources