Optimization of loops - How to implement list-comprehensions - python-3.x

I am writing a function, get_moduli,
that takes an arbitrary number of lists of Cartesian coordinates as input,
and returns the radii as a list. The function behaves correctly but is a bit too long,
and could perhaps be optimized using list comprehensions. Any suggestions?
# Sample input:
x = [1, 2, 3]
y = [1, 3, 5]
z = [1, 4, 7]
def get_moduli(*args):
"""Moduli of arbitrary number of vectors."""
moduli = []
for container in args:
for i in range(len(container)):
container[i - 1] = container[i - 1] ** 2
for i in range(len(args)):
sum_of_squares = 0
for j in range(len(args[i])):
sum_of_squares += args[j][i]
moduli.append(sum_of_squares ** .5)
return moduli
# Run function on sample input:
get_moduli(x, y, z)
# Desired outcome should be as follows:
# [(1 ** 2 + 1 ** 2 + 1 ** 2) ** .5,
# (2 ** 2 + 3 ** 2 + 4 ** 2) ** .5,
# (3 ** 2 + 5 ** 2 + 7 ** 2) ** .5]
Returns correct answer:
[1.7320508075688772, 5.385164807134504, 9.1104335791443]
But how could this function be simplified?

These two functions do what you want:
def modulus(v):
return sum(vi*vi for vi in v)**0.5
def zipped_modulus(*args):
return [modulus(t) for t in list(zip(*args))]
zipped_modulus(x,y,z)

Took me some time to figure out that your matrix is transposed of what i thought
you can use this
def modulus(*args)
return [sum([v**2 for v in vector])**.5 for vector in zip(*args)]

# Sample input:
x = [1, 2, 3]
y = [1, 3, 5]
z = [1, 4, 7]
def get_moduli1(*args):
return list(map(lambda x: sum(y**2 for y in x)**0.5 , zip(*args)))
print(get_moduli1(x, y, z))
output
[1.7320508075688772, 5.385164807134504, 9.1104335791443]

Related

How do I store factors of polynomials in a list in sympy?

Suppose I have x^6-1 that I would like to factor, using .factor I get my irreducible factors, but I want those factors in a list. I tried using .factor_list() But it doesn't give me my desired result instead stores them in a tuple and there is always a 1 beside the factors. I want each factored polynomial in a list on its own, how can I do that if possible?
Like for example,
from sympy import Symbol, factor, Poly
x = Symbol('x')
p = x**6 - 1
factors = factor(p)
factors
that gives me these factors 4 irreducible factors, how do I store them in a list not as a tuple?
You can break a product into a list of factors by forcing the factored result to be treated like a product (whether it is or not); this will give you a tuple of factors. You can use list to change this to a list if needed:
>>> from sympy import Mul
>>> list(Mul.make_args(factor(x**6-1)))
[x + 1, x - 1, x**2 + x + 1, x**2 - x + 1]
You said "I want each factored polynomial in a list on its own, how can I do that if possible"; is this what you mean:
>>> [[i] for i in Mul.make_args(factor(x**6-1))]
[[x + 1], [x - 1], [x**2 + x + 1], [x**2 - x + 1]]
What do you want to do with arguments that are repeated?
>>> [b for b,e in factor_list((x+1)*(x**6-1))[1] for i in range(e)]
[x - 1, x + 1, x + 1, x**2 - x + 1, x**2 + x + 1]
>>> [b for b,e in factor_list((x+1)*(x**6-1))[1]]
[x - 1, x + 1, x + 1, x**2 - x + 1, x**2 + x + 1]
>>> from collections import Counter
>>> [b**(e*c) for (b,e),c in Counter(factor_list((x+1)*(x**6-1))[1]).items()]
[x - 1, (x + 1)**2, x**2 - x + 1, x**2 + x + 1]
I don't think that last step should be necessary to combine like factors. I will report that as a bug since the docstring shows another example in which a factor with multiplicity of 2 appears once in a tuple.
The output of factor_list is the leading coefficient and then a list of tuples of monic irreducible factors along with their multiplicity:
In [13]: factor_list(x**6 - 1)
Out[13]:
⎛ ⎡ ⎛ 2 ⎞ ⎛ 2 ⎞⎤⎞
⎝1, ⎣(x - 1, 1), (x + 1, 1), ⎝x - x + 1, 1⎠, ⎝x + x + 1, 1⎠⎦⎠
You can just extract the part of the return value that you want from the factor_list output:
In [12]: [f for f, m in factor_list(x**6 - 1)[1]]
Out[12]:
⎡ 2 2 ⎤
⎣x - 1, x + 1, x - x + 1, x + x + 1⎦
I guess you could use as_terms() method
factors.as_terms()[1]
This would produce the following list:
[x - 1, x + 1, x**2 - x + 1, x**2 + x + 1]

Compare neighbouring cells in a 2d array

Suppose this is a 3X3 matrix and I need to find the number of elements that are greater than their neighbours.
[[1 2 7],
[4 5 6],
[3 8 9]]
Neighbours are those cells whose corners touch each other.
1 has neighbours 2,4,5.
2 has neighbours 1,7,4,5,6.
7 has 2,5,6.
5 has 1,2,7,4,6,3,8,9 and so on.
This problem can be solved in two steps/functions: 1) get_neighbors(matrix, r, c), and 2) compare_neighbors(matrix). In the 2nd function, compare_neighbors we just call get_neighbors and passing all coordinates by leveraging itertools.product.
# code snippet:
from itertools import product
def get_neighbors(matrix, r, c):
sum((row[c -(c>0): c+2]
for row in matrix[r -(r>0):r+2]), []) # sum() beats itertools.chain()
vals.remove(grid[r][c]) # rm itself.
return set(vals) # keep distinct nums. ONLY
def compare_neighbors(matrix):
ROW, COL = len(matrix), len(matrix[0])
result = []
for x, y in product(range(ROW), range(COL)):
current = matrix[x][y]
all_nums = get_neighbors(matrix, x, y)
if all(x < current for x in all_nums):
result.append(current)
return result
Program running:
grid = [[1, 5, 4, 9],
[2, 6, 3, 2],
[8, 3, 6, 3],
[5, 4, 7, 1]]
matrix = [[1, 2, 7],
[4, 5, 6],
[3, 8, 9]]
print(f' {compare_neighbors(matrix)} ') # [7, 9]
print(f' {compare_neighbors(grid) } ') # [9, 8, 7]
You need to tackle different problems:
ensure you got data that fits the problemstatement - a matrix of strings f.e. does not work nor does a non-quadratic data input
get the actual neighbouring indexes based on a potential neighbourhood
check all neighbours for bigger then testing-index
You can get the dimensions directly from the provided data (after assertioning it conforms to some base rules) and provide a generic check based on this like so:
# different neighbourhood tuples
neigh8 = tuple((a,b) for a in range(-1,2) for b in range(-1,2))
neigh4 = tuple((a,b) for (a,b) in neigh8 if a or b)
def assertions(data):
"""Check if data is list of lists and all dims are same.
Check if all elements are either ints or floats.
Exit with exception if not."""
assert isinstance(data, list)
outer_dim = len(data)
for inner in data:
assert outer_dim == len(inner), f"Inner element not of len {outer_dim}: {inner}"
assert isinstance(inner, list), f"Inner element not list: {inner}"
allNumbers = all(isinstance(i, (int, float)) for i in inner)
assert allNumbers, f"Not all elements ints or floats: {inner}"
return outer_dim
def test_surrounded_by_lower_numbers(data, idx, n_idx):
"""Test one element at 'idx' in 'data' for a given neighbourhood 'n_idx'
and return True if surrounded only by smaller numbers."""
def get_idx(data, idx, n_idx):
"""Get all indexes that conform to the given neighbourhood and are
not identical to idx nor out of bounds."""
n = []
for (a,b) in n_idx:
# identical to input idx
if (idx[0]+a , idx[1]+b) == idx:
continue
# out of bounds
if idx[0]+a < 0 or idx[1]+b < 0:
continue
if idx[0]+a >= len(data) or idx[1]+b >= len(data):
continue
n.append( (idx[0]+a , idx[1]+b ))
return n
value = data[idx[0]][idx[1]]
n = get_idx(data, idx, n_idx)
# check if all are smaller as the current value
return all (data[a][b] < value for a,b in n)
def test_matrix(matrix, n_idx = neigh8):
"""Check all matrix values for given neighbourhood. Output alle values that are
surrounded only by strictly smaller values."""
print()
for i in matrix:
for n in i:
print(f"{float(n):>5.2f} ".replace(".00"," "), end=" ")
print()
print()
dim = assertions(matrix)
for (a,b) in ((a,b) for a in range(dim) for b in range(dim)):
if test_surrounded_by_lower_numbers(matrix,(a,b)):
print(f"{(a,b)} = {matrix[a][b]} is biggest.")
Program:
# 3 x 3
test_matrix( [[1, 2, 7], [4, 5, 6], [3, 8, 9]] )
# 5 x 5
test_matrix([[1, 2, 7, 11, 9],
[4, 5, 6, -2, .5],
[9.1, 3,99.99, 8, 9.7],
[1,2,3,4,5],
[40,50,60,70,80]])
Output for 3x3 testcase:
1 2 7
4 5 6
3 8 9
(0, 2) = 7 is biggest.
(2, 2) = 9 is biggest.
Output for 5x5 testcase:
1 2 7 11 9
4 5 6 -2 0.50
9.10 3 99.99 8 9.70
1 2 3 4 5
40 50 60 70 80
(0, 3) = 11 is biggest.
(2, 0) = 9.1 is biggest.
(2, 2) = 99.99 is biggest.
(2, 4) = 9.7 is biggest.
(4, 4) = 80 is biggest.

Remove non-conjugates from complex numbers list

I have two lists, one contains the real part of imaginary numbers, the other contains the imaginary part of the same numbers. I want to remove from both lists the imaginary numbers that do not have a conjugate.
For example, the following lists x = [3, 4, 2, 7, 4] and y = [2, -1, 0, 6, 1] represent the numbers :
3 + 2j <- no conjugate (to remove)
4 - 1j <- conjugate (to keep)
2 + 0j <- real (to keep)
4 + 1j <- conjugate (to keep)
7 + 6j <- no conjugate (to remove)
The expected result is the following :
new_x = [4, 2, 4]
new_y = [-1, 0, 1]
Any idea how i can achieve this ? Thanks
This script will find complex conjugates from lists x and y:
x = [3, 4, 2, 7, 4]
y = [2, -1, 0, 6, 1]
tmp = {}
for r, i in zip(x, y):
tmp.setdefault(i, set()).add(r)
x_out, y_out = [], []
for r, i in zip(x, y):
if i==0 or r in tmp.get(-i, []):
x_out.append(r)
y_out.append(i)
print(x_out)
print(y_out)
Prints:
[4, 2, 4]
[-1, 0, 1]

Finding maximal submatrix of all 1's - missing argument error

Program that finds the maximal rectangle containing only 1's of a binary matrix with the maximal histogram problem.
I am trying to do some tests on a code
def maximalRectangle(self, matrix):
if not matrix or not matrix[0]:
return 0
n = len(matrix[0])
height = [0] * (n + 1)
ans = 0
for row in matrix:
for i in range(n):
height[i] = height[i] + 1 if row[i] == '1' else 0
stack = [-1]
for i in range(n + 1):
while height[i] < height[stack[-1]]:
h = height[stack.pop()]
w = i - 1 - stack[-1]
ans = max(ans, h * w)
stack.append(i)
return ans
# Driver Code
if __name__ == '__main__':
matrix = [[0, 1, 0, 1],
[0, 1, 0, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]]
print(maximalRectangle(matrix))
I get TypeError: maximalRectangle() missing 1 required positional argument: 'matrix' error
Solved by removing self and changing the print statement to:
print(maximalRectangle([
["1","0","1","0","0"],
["1","1","1","1","1"],
["1","1","1","1","1"],
["1","0","0","1","0"]]))

calculation of variance function equation

I have an error in this code as I want to calculate the variance between the values in the(x1) and (x2) list. any recommendation?!
def my_var(L):
s = 0
t = 0
u = 0
for i in range(0, len(L)):
s += L[i]
t = s/len(L)
u += ((L[i]-t)*(L[i]-t))
return u / len(L)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)
You're doing many things incorrectly based on how I learned prob and stats. You need to calculate the average (mean) and then sum each value subtracted by the mean, squared. Then finally take that numerator and divide by 1 less than the sample size (n-1).
def my_var(L):
mean = float(sum(L) / Len(L))
numerator = 0
for i in range(0, len(L)):
numerator += (L[i]-mean)**2
return numerator / (len(L) - 1)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)
Without using sum:
def my_var(L):
my_sum = 0
mean = 0
numerator = 0
for i in range(0, len(L)):
my_sum += L[i]
mean = float(my_sum / len(L))
for i in range(0, len(L)):
numerator += (L[i]-mean)**2
return numerator / (len(L) - 1)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)
Try numpy.
import numpy as np
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = np.var(x1)
v2 = np.var(x2)
Thank you #billy_ferguson. I have modified your code and it works. Execuse me, I am still an amateur but could you replace float and sum function and use simpler arithmetic operators as len(L) and += in this line mean = float(sum(L) / len(L))
def my_var(L):
mean = 0
numerator = 0
for i in range(0, len(L)):
mean = float(sum(L) / len(L))
numerator += (L[i]-mean)**2
return numerator / len(L)
x1 = [1, 3, 4, -3, 8]
x2 = [1, -4, 7, 2]
v1 = my_var(x1)
v2 = my_var(x2)
print(v1)
print(v2)

Resources