So let's say my matrix looks like this (always a square):
a1 a2 a3
b1 b2 b3
c1 c2 c3
I want so that elements in the square, (a1, a2, b1, b2)
, (a2, a3, b2, b3)
, etc
were not similar — meaning : a1 != a2 != b1 != b2
.
I have this code for recursively generating the matrix:
def generate(elements):
if not elements:
return (),
final = []
for items in generate(elements[:-1]):
for item in elements[-1]:
final.append(items (item,))
return final
def product(*args, repeat=1):
pools = [list(pool) for pool in args] * repeat
return list(generate(pools))
def main():
D = 3
combinations = product([0, 128, 196], repeat=D)
matrices = product(combinations, repeat=D)
return matrices
where elements
is a list of integers (unknown number), let's say [0, 128, 196]
and repeat
is the size of the square matrix.
I want somewhere in the function to apply the rule, so that it will only generate matrices according to that rule that I mentioned.
So in the end the final result would be all the possible variations of 3x3 matrices but with that rule applied.
Would prefer to do it without importing pandas or anything like that.
CodePudding user response:
Here is a possibility:
- Generate all possible matrices using
itertools.permutations
andnumpy.reshape
; - Check if a matrix is suitable using
numpy.diff
to test for equal adjacent elements.
from more_itertools import distinct_permutations
from numpy import array, diff, count_nonzero
def check_matrix(m):
d_vert = diff(m, axis=0) # vertically adjacent
if count_nonzero(d_vert) < d_vert.size:
return False
d_hori = diff(m, axis=1) # horizontally adjacent
if count_nonzero(d_hori) < d_hori.size:
return False
d_dia1 = d_vert[:,:-1] d_hori[1:,:] # northwest-southeast diagonally adjacent
if count_nonzero(d_dia1) < d_dia1.size:
return False
d_dia2 = d_hori[:-1,:] - d_vert[:,:-1] # southwest-northeast diagonally adjacent
return count_nonzero(d_dia2) == d_dia2.size
def gen_matrices(h,w, elements):
for p in distinct_permutations(elements, h*w):
m = array(p).reshape((h,w))
if check_matrix(m):
yield m
for m in gen_matrices(2, 3, [1,2,3,4,1,2]): # should be 8 results with 3 and 4 in the middle column
print(m)
# [[1 3 1]
# [2 4 2]]
# [[1 3 2]
# [2 4 1]]
# [[1 4 1]
# [2 3 2]]
# [[1 4 2]
# [2 3 1]]
# [[2 3 1]
# [1 4 2]]
# [[2 3 2]
# [1 4 1]]
# [[2 4 1]
# [1 3 2]]
# [[2 4 2]
# [1 3 1]]
Documentation:
- numpy.diff
- numpy.reshape
- numpy.count_nonzero
- numpy.size
- itertools.permutations
- more_itertools.distinct_permutations
CodePudding user response:
solved it by adding a new function that checks each 2 lines. little bit slow but it works.
def square_chec(row1, row2):
if row1[-1] == row2[-1]:
return False
for num in range(len(row1)-1):
if row2[num 1] == row1[num] or row2[num] == row1[num] or row1[num 1] == row2[num] or row2[num] == row1[num]:
return False
return True
def generate(elements):
if not elements:
return (),
final = []
for items in generate(elements[:-1]):
for item in elements[-1]:
if items:
if items[-1] != item:
if type(item) == tuple:
if square_chec(items[-1], item):
final.append(items (item,))
else:
final.append(items (item,))
else:
final.append(items (item,))
return final