How to create a numpy matrix, whose values meet several conditions? - python

I want to create a matrix, that meets this condition at first:
e.g. if a value m[2][1] == 0 <-> m[1][2] in {0,1}
For this one I use an upper triangular matrix like:
m = np.ones((6, 6), int)
m = np.triu(m, 1)
And I change some random values of the remaining to zero, until a certain percentage is achieved:
MaxPer = 0.75
i, e = np.count_nonzero(m), np.count_nonzero(m)
MAX = np.round(MaxPre*e)
while i > MAX:
m[np.random.randint(len(m[0][:]))][np.random.randint(len(m[0][:]))] = 0
i = np.count_nonzero(m)
Now the second criteria is the one I am struggling with:
if m[1][2] == 1 & m[1][3] == 0 <-> m[2][3] == 0
I want to check, if all values in m satisfy this condition (indices 1,2,3 are examples). If not, I want to change the value of m[2][3] to zero. I tried the following code with for-loops, but it overwrites all the values to zero.
for k in range(len(m[0][:])):
for l in range(k, len(m[0][:])):
for j in range(l,len(m[0][:])):
if matrix[k][l] == 1 & matrix[k][j] == 0:
matrix[l][j] = 0
Is there a simple way to this without the loops?

I think imposing your second condition indeed causes zeroing of the matrix.
Are you sure you want
m[i][j] == 1 & m[i][k] == 0 <-> m[j][k] == 0
without any dependencies between i, j, and k?
Maybe you want something like this (which would require a few changes in the fors)?
m[i][i+1] == 1 & m[i][i+2] == 0 <-> m[i+1][i+2] == 0

Related

Replace Adjacent Elements of Circular Array to Make All Elements Equal

You are given a circular array A containing N integers. You can perform the
following operation on this array any number of items:
• For each i, replace A[i] by A[i-1], A[i] or A[i+1] i.e. you can keep the
current element or replace it by an adjacent element . Note that due to
circularity of the array adjacent elements exist even for the first and
the last element. In particular, A[i-1] for i=0 is the last element.
Determine the minimum number of steps needed to make all the elements of
the array equal.
Input Format
The first line contains an integer, N, denoting the number of elements in A.
Each line i of the N subsequent lines (where 0 $i< N) contains an integer
describing A[i].
Constraints
1 <= N <= 10^3
Sample input: 4 2 2 1 1 => Sample output: 1
Sample input:3 1 1 1 => Sample output: 0
Sample input:4 1 2 3 4 => Sample output: 2
I build the following code, it passes all visible test cases on platform, but not passing invisible test cases(that i'm not sure, what are they).Please help me to find any edge cases, if i forgot something here.
from collections import Counter
def make_equal(A):
count = 0
idx = []
map = Counter(A)
value = sorted(map.values(), reverse=True)[0]
for k, v in map.items():
if v == value:
key = k
for i, val in enumerate(A):
if val == key:
idx.append(i)
new_set = set(idx)
while len(new_set) < len(A):
for j in idx[:]:
l = (j + 1) % len(A)
m = (j - 1) % len(A)
idx.append(m)
idx.append(j)
idx.append(l)
count += 1
new_set = set(idx)
return count
print(make_equal(A))

Efficient way to find if a Matrix is Sub-Matrix of another one?

Given two matrices A and B.
Is there efficient or more pythonic way to find if B is a Sub-Matrix of A?
The code below is worked but I got a Time limit exceeded when the matrix is so big!
Note: The matrix data structure is represented as an array of strings.
[Input]
A=[
'7283455864',
'6731158619',
'8988242643',
'3830589324',
'2229505813',
'5633845374',
'6473530293',
'7053106601',
'0834282956',
'4607924137']
B=[
'9505',
'3845',
'3530']
[Code]
def gridSearch(G, P):
# Write your code here
n=len(G) # Matrix G row number
m=len(G[0]) # Matrix G col number
r=len(P) # Matrix P row number
c=len(P[0]) # Matrix P col number
found='NO'
for i in range(n-r+1):
for j in range(m-c+1):
start_row=i
end_row=i+r
start_col=j
end_col=j+c
sub=[]
if G[start_row][start_col]==P[0][0]:
sub=[x[start_col:end_col] for x in G[start_row:end_row] ]
if (sub==P):
found='YES'
#print(i,j)
return(found)
[Expected Output]
YES
Rather than search on a letter by letter basis as you seem to be doing with your code, I would utilize the ability to search for strings within another string as follows:
def gridSearch(G, P):
g_sze = len(G)
p_sze = len(P)
p_ptr = 0
for g_ptr, g_row in enumerate(G):
if P[p_ptr] in g_row:
p_ptr += 1
if p_ptr == p_sze:
return True
else:
p_ptr = 0
if g_sze - g_ptr < p_sze-p_ptr:
return False
return False
The above code makes use of two efficiency approaches, first it searches the arrays by rows and secondly it stops searching rows when the ability to match the remaining rows of the smaller array is no longer possible
Given your second example, here is an approach which uses the string search approach and requires column alignment.
def gridSearch2(G, P):
g_sze = len(G)
p_sze = len(P)
candidates = []
# First scan for possible start postions
for row in range(g_sze - p_sze + 1):
idx = 0
while idx < g_sze - p_sze:
ptr = G[row].find(P[0], idx)
if ptr < 0:
break
candidates.append((row, ptr+idx))
idx = idx + ptr + 1
# test each possible start postion for matching follow on rows
while len(candidates) > 0:
row, idx = candidates.pop(0);
rslt = True
for pr in range(1, p_sze):
if G[row + pr].find(P[pr], idx) != idx:
rslt = False
break
if rslt:
return True
return False

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.

I need loop to do until all elements of array are equal to 0

Here is my code, it's randomly generated one of four numbers (1,2,3,4) and turns right left or up and down if consider array as a board, starting point is room [0][0]. It stops after changing one element of array to 0 but I need it to do until all elements are equal to 0, Thanks!
import numpy
import random
N = 2
M = 2
time = 0
room = numpy.ones((N, M), dtype=int)
print(room)
i = 0
j = 0
while room.all() != 0:
turn = random.choice([1, 2, 3, 4])
if turn == 1 and i > 0:
print("up")
i = i - 1
room[i][j] = 0
time += 1
elif turn == 2 and i < N - 1:
print("down")
i = i + 1
room[i][j] = 0
time += 1
elif turn == 3 and j > M - 1:
print("right")
j = j + 1
room[i][j] = 0
time += 1
elif turn == 4 and j < 0:
print("left")
j = j - 1
room[i][j] = 0
time += 1
else:
turn = random.choice([1, 2, 3, 4])
print("hit the wall")
print(room)
The all method checks whether all elements of your array are truthy (in this case, unequal to zero), so the condition in the while loop becomes False once there is a single zero in rooms.
What you actually want to check is whether any element of rooms is truthy (here, unequal to zero).
You can use while rooms.any(): ... instead (and omit the comparison to != 0).
There are two ways you can approach the problem:
First: As suggested by #timgeb:
while room.any():
Second: To use np.count_nonzero to check if there is any non-zero value in the array. Then use this condition in the while loop
while np.count_nonzero(room) > 0:
HOWEVER, when I use either of these conditions, two elements become 0 and two remain 1 and I end up in a never ending loop. That means, the problem is somewhere in your implementation of your indices.
That being said, now knowing two ways to check for non-zero elements, you need to inspect your code for implementation error.

Check for pattern recursively

*Note i refer to thing as a matrix but it is not, it is just a collection of 1's and zeros
Suppose you have a matrix that is always square (n x n). Is it possible to determine if there exists a single column/row/diagonal such that each item is a 1.
Take the matrix below for instance (True):
1 0 0
1 1 0
0 0 1
Another example (True):
1 1 1
0 0 0
0 1 0
And finally one without a solution (False):
0 1 1
1 0 0
0 0 0
Notice how there is a diagonal filled with 1's. The rule is there is either there is a solution or there is no solution. There can be any number of 1's or zeros within the matrix. All i really need to do is, if you have (n x n) then there should be a row/column/diagonal with n elements the same.
If this is not possible with recursions, please let me know what is the best and most efficient method. Thanks a lot, i have been stuck on this for hours so any help is appreciated (if you could post samples that would be great).
EDIT
This is one solution that i came up with but it gets really complex after a while.
Take the first example i gave and string all the rows together so you get:
1 0 0, 1 1 0, 0 0 1
Then add zeros between the rows to get:
1 0 0 0, 1 1 0 0, 0 0 1 0
Now if you look closely, you will see that the distances between the 1's that form a solution are equal. I dont know how this can be implemented though.
In search for an elegant solution I came up with this:
class LineOfOnesChecker(object):
_DIAG_INDICES = (lambda i: i, lambda i: -i - 1)
def __init__(self, matrix):
self._matrix = matrix
self._len_range = range(len(self._matrix))
def has_any(self):
return self.has_row() or self.has_col() or self.has_diag()
def has_row(self):
return any(all(elem == 1 for elem in row)
for row in self._matrix)
def has_col(self):
return any(all(self._matrix[i][j] == 1 for i in self._len_range)
for j in self._len_range)
def has_diag(self):
return any(all(self._matrix[transf(i)][i] == 1 for i in self._len_range)
for transf in self._DIAG_INDICES)
Usage:
print LineOfOnesChecker(matrix).has_any()
You can have a list of n 1's and do an 'AND' for your sets of diagonal elements, row elements and column elements and if any of those AND operation results in a TRUE, then you have your valid pattern.
import sys
matrix = [[1,0,1],[1,0,1],[1,0,1]]
transpose = zip(*matrix)
diagonal1 = []
for n,elem in enumerate(matrix):
diagonal1.append(elem[n])
diagonal2 = []
for n,elem in enumerate(transpose):
diagonal2.append(elem[n])
for row in matrix:
if reduce(lambda x,y: x and y, row):
print True
sys.exit()
for row in transpose:
if reduce(lambda x,y: x and y, row):
print True
sys.exit()
if (reduce(lambda x,y: x and y, diagonal1) or reduce(lambda x, y: x and y, diagonal2)):
print True
sys.exit()
From what I understand of the problem, you just need to check whether any row, coloumn or diagonal consists entirely of '1's. This can be done very easily using all in Python, so I don't get why you want to do this recursively.
The more obvious solution (in my mind) is something like this:
#! /usr/bin/env python
boards=[
((0,1,0),(1,0,1),(0,1,0)),
((1,1,1),(0,0,0),(0,0,0)),
((0,0,0),(1,1,1),(0,0,0)),
((0,0,0),(0,0,0),(1,1,1)),
((1,0,0),(1,0,0),(1,0,0)),
((0,1,0),(0,1,0),(0,1,0)),
((0,0,1),(0,0,1),(0,0,1)),
((1,0,0),(0,1,0),(0,0,1)),
((0,0,1),(0,1,0),(1,0,0)),
((0,0,0),(0,0,0),(0,0,0))
]
def check(board):
for row in board:
if all(row):
return True
for col in xrange(len(board)):
vector=[board[row][col] for row in xrange(len(board))]
if all(vector):
return True
diag1=[board[i][i] for i in xrange(len(board))]
if all(diag1):
return True
diag2=[board[i][i] for i in xrange(len(board)-1,-1,-1)]
if all(diag2):
return True
return False
if __name__=='__main__':
for board in boards:
if check(board):
print "Yes"
else:
print "No"

Categories