Python Two dimensional condition - python

I am unsure how to phrase a conditional loop. I would like to create a NxN array consisting of elements which are equal to either 1 or -1. I have created a 3x3 array to begin with, which when printed consists of numbers between 0 and 1.
col = 3
row = 3
mymatrix = np.random.rand(col,row)
I would like to set their values to either 1 or -1, depending on whether the value they have been assigned is greater than or equal to 0.5.
for i in range(0,2):
for j in range(0,2):
if mymatrix[i,j] <= 0.5:
mymatrix[i,j] = -1.0
elif mymatrix[i,j] >= 0.5:
mymatrix[i,j] = 1.0
print mymatrix
For some reason, this prints a 3x3 matrix with only the inner 4 elements as 1 or -1.
[[-1, 1,0.19343979]
[ 1, -1, 0.59891168]
[ 0.02766664, 0.73244162, 0.41541223]]
I know that mymatrix[2,2] is 0.41541223, so I cannot understand why this is not being looped through.

Your Problem
You need to loop over all rows and columns:
for i in range(row):
for j in range(col):
You only loop over the first two:
col = 3
row = 3
In Python range(start, end) gives a range starting form start inclusive and end exclusive.
for i in range(0,2):
for j in range(0,2):
BTW, in Python rows are the first dimension so this would be better:
mymatrix = np.random.rand(row, col)
even though both row and col have the same value in your case.
Better Solution
Working with NumPy arrays, you should avoid loops as much as possible,
because loops can be really slow. To my experience those loops over NumPy arrays can be even slower than loops over Python lists.
Therefore, better do:
np.where(mymatrix <= 0.5, -1, 1)
This is a vectorized version that is much faster.
One of the goals using NumPy is often speed.
where(condition, [x, y])
Return elements, either from x or y, depending on condition.

Your error is in upper bound:
mymatrix = np.random.rand(col,row)
for i in range(0,3):
for j in range(0,3):
if mymatrix[i,j] <= 0.5:
mymatrix[i,j] = -1.0
elif mymatrix[i,j] >= 0.5:
mymatrix[i,j] = 1.0
print (mymatrix)

Related

I need to transform each element of a matrix if a a condition is met using a comprehension

I have the matrix "array". I need to traverse this matrix, and test each element of it, if element x!=0 else x=0. I've tried to use this but it does not accept the else. To simplify, the dimension is fixed at 500x9. I have done this:
ds_Entropy = [array[i][j] for i in range(500) for j in range(9) if array[i][j] !=0 else "0" for i in range(500) for j in range(9)]
Everything from the else onward is wrong. The above description is simplified, what I really need is:
for a matrix M with elements Mij, if MiJ !=0 then calculate Rij = sum(all column elements of Mij)*LOG(Mij) if Mij !=0 else Mij = 0
If I understood correctly, for each element you are trying to print the value if different than zero and "0" if equals zero. You can do that inline like this:
import numpy as np
r_size = 500
c_size = 9
array = np.random.randint(10, size = (r_size, c_size))
ds_Entropy = [array[i][j] if array[i][j] != 0 else "0" for i in range(r_size) for j in range(c_size)]

Writing constraints for grid squares in python z3

So I'm working with Z3 in python and I have to write constraints/conditions for a "marvellous square" which is just a grid of numbers. the conditions for a marvellous square are:
It is filled with all the integers from 1 to 𝑛**2
Every row in the square sums to the same number t
Every column in the square also sums to that same number t
Both diagonals sum to that same number t
Using the list constraints I've been been able to do the first 1:
aGrid = [ [ Int("x_%s_%s" % (i+1, j+1)) for j in range(n) ] for i in range(n) ]
conditionOne = [ And(1 <= aGrid[i][j], aGrid[i][j] <= n**2) for i in range(n) for j in range(n) ]
So in line 1 I create the instance for an n-by-n grid.
In line 2, I create the first condition where each of the entries is from 1 to n squared
The issue I have now is getting the sum of each column and row and equating them to the same thing in the same constraint. As well as the diagonal constraints. I have a feeling they will all be done in the same constraint, but the list comprenhension is confusing.
Here's one way to do it:
from z3 import *
# Grid size
n = 4
# Total and grid itself
t = Int('t')
grid = [[Int("x_%s_%s" % (i+1, j+1)) for j in range(n)] for i in range(n)]
s = Solver()
# Range constraint
allElts = [elt for row in grid for elt in row]
for x in allElts: s.add(And(x >= 1, x <= n*n))
# Distinctness constraint
s.add(Distinct(*allElts))
# Each row
for row in grid: s.add(t == sum(row))
# Each column
for i in range(n): s.add(t == sum([grid[j][i] for j in range(n)]))
# Each diagonal
s.add(t == sum([grid[i][i] for i in range(len(grid))]))
s.add(t == sum([grid[n-i-1][i] for i in range(len(grid))]))
# Solve:
if s.check() == sat:
m = s.model()
print(f't = {m[t]}')
for row in grid:
for elt in row:
print(f'{str(m[elt]):>3s}', end="")
print("")
else:
print("No solution")
When I run this, I get:
t = 34
7 4 14 9
11 16 2 5
6 13 3 12
10 1 15 8
Which satisfies the constraints.
Note that as n gets larger the time z3 will spend in solving will increase quite a bit. Here're are two ideas to make it go much faster:
Note that t depends on n. That is, if you know n, you can compute t from it. (It'll be n * (n*n + 1) / 2, you can justify to yourself why that's true.) So, don't make t symbolic, instead directly compute it and use its value.
Computing over Int values is expensive. Instead, you should use bit-vector values of minimum size. For instance, if n = 6, then t = 111; and you only need 7-bits to represent this value. So, instead of using Int('x'), use BitVec('x', 7). (It's important that you pick a large enough bit-vector size!)
If you make the above two modifications, you'll also see that it performs better than Int values only.

Similarity Measure in Python

I am working on this coding challenge named Similarity Measure. Now the problem is my code works fine for some test cases, and failed due to the Time Limit Exceed problem. However, my code is not wrong, takes more than 25 sec for input of range 10^4.
I need to know what I can do to make it more efficient, I cannot think on any better solution than my code.
Question goes like this:
Problems states that given an array of positive integers, and now we have to answer based upon the Q queries.
Query: Given two indices L,R, determine the maximum absolute difference of index of two same elements lies between L and R
If in a range, there are no two same inputs then return 0
INPUT FORMAT
The first line contains N, no. of elements in the array A
The Second line contains N space separated integers that are elements of the array A
The third line contains Q the number of queries
Each of the Q lines contains L, R
CONSTRAINTS
1 <= N, Q <= 10^4
1 <= Ai <= 10^4
1 <= L, R <= N
OUTPUT FORMAT
For each query, print the ans in a new line
Sample Input
5
1 1 2 1 2
5
2 3
3 4
2 4
3 5
1 5
Sample Output
0
0
2
2
3
Explanation
[2,3] - No two elements are same
[3,4] - No two elements are same
[2,4] - there are two 1's so ans = |4-2| = 2
[3,5] - there are two 2's so ans = |5-3| = 2
[1,5] - there are three 1's and two 2's so ans = max(|4-2|, |5-3|, |4-1|, |2-1|) = 3
Here is my algorithm:
To take the input and test the range in a different method
Input will be L, R and the Array
For difference between L and R equal to 1, check if the next element is equal, return 1 else return 0
For difference more than 1, loop through array
Make a nested loop to check for the same element, if yes, store the difference into maxVal variable
Return maxVal
My Code:
def ansArray(L, R, arr):
maxVal = 0
if abs(R - L) == 1:
if arr[L-1] == arr[R-1]: return 1
else: return 0
else:
for i in range(L-1, R):
for j in range(i+1, R):
if arr[i] == arr[j]:
if (j-i) > maxVal: maxVal = j-i
return maxVal
if __name__ == '__main__':
input()
arr = (input().split())
for i in range(int(input())):
L, R = input().split()
print(ansArray(int(L), int(R), arr))
Please help me with this. I really want to learn a different and a more efficient way to solve this problem. Need to pass all the TEST CASES. :)
You can try this code:
import collections
def ansArray(L, R, arr):
dct = collections.defaultdict(list)
for index in range(L - 1, R):
dct[arr[index]].append(index)
return max(lst[-1] - lst[0] for lst in dct.values())
if __name__ == '__main__':
input()
arr = (input().split())
for i in range(int(input())):
L, R = input().split()
print(ansArray(int(L), int(R), arr))
Explanation:
dct is a dictionary that for every seen number keeps a list of indices. The list is sorted so lst[-1] - lst[0] will give maximum absolute difference for this number. Applying max to all this differences you get the answer. Code complexity is O(R - L).
This can be solved as O(N) approximately the following way:
from collections import defaultdict
def ansArray(L, R, arr) :
# collect the positions and save them into the dictionary
positions = defaultdict(list)
for i,j in enumerate(arr[L:R+1]) :
positions[j].append(i)
# create the list of the max differences in index
max_diff = list()
for vals in positions.values() :
max_diff.append( max(vals) - min(vals) )
# now return the max element from the list we have just created
if len(max_diff) :
return max(max_diff)
else :
return 0

Comparing 2 arrays for tolerance

What I am trying to do is tax an array, transpose it , subtract the two arrays and then see if the difference of each cell is with a certain tolerance. I am able to get a subtracted array - but I don't know how to cycle through each item to compare the amounts - ideally I would test for floating-point near-equality; and return true - if all items are with a tolerance and false otherwise - not sure how do to this last step as well.
import numpy as np
a = np.array(([[1, 2, 3], [2, 3, 8],[ 3, 4, 1]])
b = a.transpose(1, 0)
rows = a.shape[1]
col = a.shape[0]
r = abs(np.subtract(a, b)) # abs value of 2 array
i = 0
while i < rows:
j = 0
while j < rows:
if np.any(r[i][j]) > 3: # sample using 3 as tolerance
print("false")
j += 1
print("true")
i += 1
Is this not sufficient for your needs?
tolerance = 3
result = (abs(a - b) <= tolerance).all()
In this step
r = abs(np.subtract(a, b))
you already have a matrix of distances, so all you need to do is apply comparison operator (which in numpy is applied element-wise)
errors = r > 3
which results in boolean array, and if you want to see how many elements have true value, just sum it
print( np.sum(r > 3) )
and to check if any is wrong, you can just do
print( np.sum(r > 3) > 0 ) # prints true iff any element of r is bigger than 3
There are also built-in methods, but this reasoning gives you more flexibility in expressing what is "near" or "good".

conditional sum over a range python

I have created X as folowing
num_locations = 2
X= [ ]
for n in range(num_locations):
X.append([0 for j in range(num_locations)])
Now I want to sum these X[n][m] values for the case n != m . Such that the result should be like
X[0][1]+X[1][0]
Is there a way to do that with the sum formulation ?
X[n][m] for n in range(num_locations)for m in range(num_locations))
This is effectively taking the sum of the non-diagonal elements of your 2D array. One option using Numpy could simply be to subtract the sum of the main diagonal (np.trace) from the sum of the entire array.
num_locations = 2
X= [[1,2],[2,1]]
import numpy as np
s = np.sum(X) - np.trace(X)
print(s)
Outputs:
4
You can simply use enumerate
>>> sum(o for i, a in enumerate(X) for j, o in enumerate(a) if i!=j)
0
Where i and j are row (1st dim) and column (2nd dim) indices respectively
This should work
sum([sum(row) - (row[i] if len(row) < i else 0) for i,row in enumerate(X)])
It runs over every row in the 2d array, and sums it, then take out the i cell (if exists) so it won't get into sum

Categories