Related
I need to write in python3 a function that fills the bigger square with smaller squares basing on the input.
The input is a list of positive integers. Each integer is the number of squares per row. So the list [3, 8, 5, 2] means I got 4 rows of squares where first one has 3 squares, second one 8 and so on. All squares in all rows are of the same size.
The output should be description of rows distribution in the form of list of lists.
The thing is that on the output there can not be empty rows. So effectively the number of columns can not be greater than the number of rows. The rows can be split though into two or more rows. So for example for the list [3, 8, 5, 2] the function should return [[3], [5, 3], [5], [2]]:
AAA
BBBBB
BBB
CCCCC
DD
and for input [14,13,2,12] it should return [[7,7], [7,6], [2], [7,5]]:
AAAAAAA
AAAAAAA
BBBBBBB
BBBBBB
CC
DDDDDDD
DDDDD
As we can see, the number of rows and columns is in both examples equal. Of course it's not always possible but the lesser difference between the number of columns and rows, the more efficient the algorythm is - the better the square is filled. In general we aim to get as many columns as possible and as little rows as possible.
And here is the issue - the above examples used 4 input rows - the input list can have a lot of more elements (for example 200 input rows). And the problem is to find optimial way to split the rows (for example if i should split 18 as 9+9 or 6+6+6 or 7+7+4 or maybe 5+5+5+3). Because every time i split the rows basing on available columns (that depend on the number of used rows), I get more output rows and therefore I am able to use more additional available columns - and I fall into some weird loop or recursion.
I'm sorry if there is some easy solution that I don't see and thank you in advance for help <3
EDIT: Here I include example function that simply ignores the fact that the number of rows increases and just treats the number of input rows as maximum amount of columns possible:
def getSquare(x):
output = list()
ln = len(x)
for i in x:
if i <= ln:
output.append([i])
else:
split = list()
nrows = i // ln
for j in range(nrows):
split.append(ln)
if i % ln:
split.append(i % ln)
output.append(split)
return output
print(getSquare([14, 13, 2, 12]))
# returns [[4, 4, 4, 2], [4, 4, 4, 1], [2], [4, 4, 4]]
# so 4 columns and 12 rows
# columns - maximum number in the matrix
# rows - number of all elements in the matrix (length of flattened output)
# while it should return: [[7,7], [7,6], [2], [7,5]]
# so 7 columns and 7 rows
#(nr of columns should be not larger but as close to the number of rows as possible)
EDIT2: It doesn't have to return perfect square - just something as close to square as possible - for example for [4,3,3] it should return [[3,1],[3]
,[3]] while for extreme cases like [1,1,1] it should just return [[1],[1],[1]]
list = [3, 8, 5, 2] #As close to a Square as possible
def getSquare(list):
for i in range(1, max(list)+1):
output = []
num = 0
for j in list:
output.append([i]*(j//i))
num += j//i
if j%i != 0:
output[-1].append(j%i)
num += 1
if num == i:
return output
i = int( sum(list) ** (1/2) // 1)
output = []
for j in list:
output.append([i]*(j//i))
num += j//i
if j%i != 0:
output[-1].append(j%i)
num += 1
return output
for i in getSquare(list):
for j in i:
print("*"*j)
Here I just repeat the splitting process of the list until i and num become same.
Essentially when you decrease width, you increase number of rows (vice versa is also true: when you increase width, you decrease number of rows), that's why you want to as far as it's possible equalise width and height, because that would get you minimum area of covering square. From this point of view your problem looks like ternary search: minimize maximum of resulting width and height.
So we perform ternary search over width (fix it) and calculate resulting maximum side of square. Calculating function is pretty obvious:
def get_max_side(l, fixed_width): # O(len(l))
height = 0
for i in l:
height += i // fixed_width
if i % fixed_width:
height += 1
return max(fixed_width, height)
Then use it in a ternary search algorithm to find minimum of get_max_side and restore the answer using found value. Time complexity is O(len(l) * log(max_meaningful_square_width)).
I have improved an answer, adding some stop signs to generally speed up the algorithm. It also gives much more efficient answer when no ideal solution was found.
arr = [14, 13, 2, 12] # as close to a square as possible
def getSquare(lst):
output = []
mx = max(lst)
for cols in range(min(len(lst), mx), mx + 1):
out = []
rows = 0
for j in lst:
ln = j // cols
r = j % cols
out.append([cols] * ln)
rows += ln
if r:
out[-1].append(r)
rows += 1
if rows >= cols:
output = out
else:
break
return output
for i in getSquare(arr):
for j in i:
print("*" * j)
Given a numpy ndarray like the following
x = [[4.,0.,2.,0.,8.],
[1.,3.,0.,9.,5.],
[0.,0.,4.,0.,1.]]
I want to find the indices of the top k (e.g. k=3) elements of each row, excluding 0, if possible. If there are less than k positive elements, then just return their indices (in a sorted way).
The result should look like (a list of array)
res = [[4, 0, 2],
[3, 4, 1],
[2, 4]]
or just one flatten array
res = [4,0,2,3,4,2,2,4]
I know argsort can find the indices of top k elements in a sorted order. But I am not sure how to filter out the 0.
You can use numpy.argsort with (-num) for getting index as descending. then use numpy.take_along_axis for getting values base index of 2D sorted.
Because you want to ignore zero you can insert zero for other columns after three (as you mention in the question). At the end return value from the sorted values that is not zero.
x = np.array([[4.,0.,2.,0.,8.],[1.,3.,0.,9.,5.],[0.,0.,4.,0.,1.]])
idx_srt = np.argsort(-x)
val_srt = np.take_along_axis(x, idx_srt, axis=-1)
val_srt[:, 3:] = 0
res = idx_srt[val_srt!=0]
print(res)
[4 0 2 3 4 1 2 4]
Try one of these two:
k = 3
res = [sorted(range(len(r)), key=(lambda i: r[i]), reverse=True)[:min(k, len([n for n in r if n > 0]))] for r in x]
or
res1 = [np.argsort(r)[::-1][:min(k, len([n for n in r if n > 0]))] for r in x]
I came up with the following solution:
top_index = score.argsort(axis=1) # score here is my x
positive = (score > 0).sum(axis=1)
positive = np.minimum(positive, k) # top k
# broadcasting trick to get mask matrix that selects top k (k = min(2000, num of positive scores))
r = np.arange(score.shape[1])
mask = (positive[:,None] > r)
top_index_flatten = top_index[:, ::-1][mask]
I compare my result with the one suggested by #I'mahdi and they are consistent.
When we multiply two matrices A of size m x k and B of size k x n we use the following code:
#for resultant matrix rows
for i in range(m):
#for resultant matrix column
for j in range(n):
for l in range(k):
#A's row x B's columns
c[i][j]=c[i][j]+a[i][l]*b[l][j]
are my comments in the code right explanation of the loops? Is there a better explanation of the loops or is there a better thought process to code matrix multiplication?
EDIT1: I am not looking for a better code. My question is about the thought process that goes in when we transform the math of matrix multiplicate into code.
Your code is correct but if you want to add detail comment/explanation like you ask for you can do so:
#for resultant matrix rows
for i in range(m):
#for resultant matrix column
for j in range(n):
#for each entry in resultant matrix we have k entries to sum
for l in range(k):
#where each i, j entry in the result matrix is given by multiplying the
#entries A[i][l] (across row i of A) by the entries B[l][j] (down
#column j of B), for l = 1, 2, ..., k, and summing the results over l:
c[i][j]=c[i][j]+a[i][l]*b[l][j]
EDIT: if you want a better explanation of the loop or thought process than take out #A's row x B's columns comments. and replace it with "where each i, j entry in the result matrix is given by multiplying the entries A[i][l] (across row i of A) by the entries B[l][j] (down column j of B), for l = 1, 2, ..., k, and summing the results over " also don't use l as an iterator it looks like a 1
You can use numpy.dot function. Here's the documentation. Example (extracted from the documentatio):
> a = [[1, 0], [0, 1]]
> b = [[4, 1], [2, 2]]
> np.dot(a, b)
> array([[4, 1],
[2, 2]])
The condition that should always stand in order to do 2 matrices multiplication is that first matrix must have the same amount of rows that the other matrix has columns.
so if matrix_1 is m x n than second matrix_2 should be n x p. The result of the two will have a dimension of m x p
the Pseudocode will be:
multiplyMatrix(matrix1, matrix2)
-- Multiplies rows and columns and sums them
multiplyRowAndColumn(row, column) returns number
var
total: number
begin
for each rval in row and cval in column
begin
total += rval*cval
end
return total
end
begin
-- If the rows don't match up then the function fails
if matrix1:n != matrix2:m return failure;
dim = matrix1:n -- Could also be matrix2:m
newmat = new squarematrix(dim) -- Create a new dim x dim matrix
for each r in matrix1:rows and c in matrix2:columns
begin
end
end
In python either you can do what you did, or you can use ijk-algo, ikj-algo, psyco ikj-algo, Numpy, or SciPy to accomplish this. It appears that Numpy is the fastest and most efficient.
YOUR CODE LOOKS RIGHT AND YOUR COMMENTS ALSO DO LOOK CORRECT
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)
I have no idea how to even begin doing this
It needs to be a for loop to multiply mtrixes
for example
[[1,2],[3,4]] * [[3,4],[5,6]]
[1 , 2] , [3 , 4]
[3 , 4] *[5 , 6]
Need help much appreciated
I know 90% of dont want to code for me so that's ok
It only needs to be two square matrixes
i'm pretty sure the pattern is looking at it in the list thing
a[1][1]*b[1][1]+a[1][2]*b[2][1] a[1][1]b[1][2]+a[1][2]b[2][2]
a[2][1]b[1][1]+a[2][2]b[2][1] a[2][1]b[1][2]+a[2][2]b[2][2]
result = [] # final result
for i in range(len(A)):
row = [] # the new row in new matrix
for j in range(len(B[0])):
product = 0 # the new element in the new row
for v in range(len(A[i])):
product += A[i][v] * B[v][j]
row.append(product) # append sum of product into the new row
result.append(row) # append the new row into the final result
print(result)
Break it down. Before you try to write a function that multiplies matrices, write one that multiplies vectors. If you can do that, multiplying two matrices is just a matter of multiplying row i and column j for every element i,j of the resultant matrix.
If you look at how matrix multiplication works:
[ 1 2 ] x [ 5 6 ] = [ 1*5+2*7 1*6+2*8 ]
[ 3 4 ] [ 7 8 ] [ 3*5+4*7 3*6+4*8 ]
then you can determine a method to calculate this, e.g. if you are multiplying for element i, j of the output matrix, then you need to multiply everything in row i of the LHS matrix by everything in the column j of the RHS matrix, so that is a single for loop (as the number of elements in the row i is equal to column j).
You also need to cover every combination of i and j for the dimensions of the output matrix, which is a for loop for the columns nested inside a for loop for the rows.
The actual code is, of course, an exercise for you to implement.
>>> A=[[1,2],[3,4]]
>>> B=[[3,4],[5,6]]
>>> n=2
>>> ans=[[0]*n for i in range(n)]
>>> ans
[[0, 0], [0, 0]]
>>> for i in range(n):
... for j in range(n):
... ans[i][j]=sum((A[i][v]*B[v][j] for v in range(n)))
...
>>> ans
[[13, 16], [29, 36]]
I think you just need to simplify the formula of matrix multiplication.
We have A*B=C then:
Cij= the value in the ith row and jth column of the answer. For example above we have C12=16 and C11=13.. (note that this is the 0th position in the array so often we start from 0 instead of 1)
Cij= dot_product(row_i_of_A,column_j_of_B)=sum(row_i_of_A(v)*column_j_of_B(v) for v in range(n))
Because we want the whole answer (all of C), we need to work out all possible Cij. This means we need to try all possible pairs ij, so we loop through i in range(n), j in range(n) and do this for each possible pair.
from numpy import *
m1 = array([[1, 2, 3],[4, 5, 6] ])
m2 = array([[7, 8],[9, 10],[11, 12]])
r = array([[0, 0],[0, 0]])
s = 0
for i in range(2):
for j in range(2):
for k in range(3):
s = s + m1[i][k]*m2[k][j]
r[i][j] = s
s = 0
print(r)
I think append function is not working in a two-dimensional array when we are using numpy module, so this is the way I have solved it.
def matmul(matrix1_,matrix2_):
result = [] # final result
for i in range(len(matrix1_)):
row = [] # the new row in new matrix
for j in range(len(matrix2_[0])):
product = 0 # the new element in the new row
for v in range(len(matrix1_[i])):
product += matrix1_[i][v] * matrix2_[v][j]
row.append(product) # append sum of product into the new row
result.append(row) # append the new row into the final result
return result
u and v are constructed for visualization purpose.
from typing import List
A = [[1,0,0],[-1,0,3]]
B = [[7,0,0],[0,0,0],[0,0,1]]
def mult_mat(A:List[List[int]], B:List[List[int]]) -> List[List[int]]:
n = len(A) # Number of rows in matrix A
m = len(B[0]) # Number of columns in matrix B
ret = [[0 for i in range(m)] for j in range(n)]
for row in range(n):
u = A[row]
for col in range(m):
v = [B[i][col] for i in range(len(B))]
# Here you can calculate ret[row][col] directly without v
# But v is constructed for visualization purpose
ret[row][col] = sum([x*y for x,y in zip(u,v)])
return ret
if __name__ == '__main__':
print(mult_mat(A,B))