如何生成具有排列的矩阵,其中任何 2x2 正方形都有 4 个不同的值?
How to generate a matrix with permutations where any 2x2 square has 4 non-identical values?
假设我的矩阵看起来像这样(总是一个正方形):
a1 a2 a3
b1 b2 b3
c1 c2 c3
我希望正方形 (a1, a2, b1, b2)
、(a2, a3, b2, b3)
、etc
中的元素不相似 — 意思是:a1 != a2 != b1 != b2
.
我有递归生成矩阵的代码:
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
其中 elements
是整数列表(未知数),假设 [0, 128, 196]
和 repeat
是方阵的大小。
我想在函数的某处应用规则,以便它只会根据我提到的规则生成矩阵。
因此最终结果将是 3x3 矩阵的所有可能变体,但应用了该规则。
宁愿不导入 pandas 或类似的东西。
有一种可能:
- 使用
itertools.permutations
和numpy.reshape
生成所有可能的矩阵;
- 检查矩阵是否适合使用
numpy.diff
来测试相邻元素是否相等。
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]]
文档:
通过添加一个检查每 2 行的新函数解决了这个问题。有点慢,但它有效。
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
假设我的矩阵看起来像这样(总是一个正方形):
a1 a2 a3
b1 b2 b3
c1 c2 c3
我希望正方形 (a1, a2, b1, b2)
、(a2, a3, b2, b3)
、etc
中的元素不相似 — 意思是:a1 != a2 != b1 != b2
.
我有递归生成矩阵的代码:
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
其中 elements
是整数列表(未知数),假设 [0, 128, 196]
和 repeat
是方阵的大小。
我想在函数的某处应用规则,以便它只会根据我提到的规则生成矩阵。
因此最终结果将是 3x3 矩阵的所有可能变体,但应用了该规则。
宁愿不导入 pandas 或类似的东西。
有一种可能:
- 使用
itertools.permutations
和numpy.reshape
生成所有可能的矩阵; - 检查矩阵是否适合使用
numpy.diff
来测试相邻元素是否相等。
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]]
文档:
通过添加一个检查每 2 行的新函数解决了这个问题。有点慢,但它有效。
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