如何生成一个具有排列的矩阵,其中任何 2x2 平方都有 4 个不相同的值?

How to generate a matrix with permutations where any 2x2 square has 4 non-identical values?

提问人:Saba 提问时间:12/20/2021 最后编辑:martineauSaba 更新时间:12/21/2021 访问量:204

问:

因此,假设我的矩阵看起来像这样(始终是正方形):

a1 a2 a3
b1 b2 b3
c1 c2 c3

我希望正方形中的元素 , , 不相似 — 意思是 : 。(a1, a2, b1, b2)(a2, a3, b2, b3)etca1 != 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 矩阵的所有可能变体,但应用了该规则。

宁愿在不导入熊猫或类似东西的情况下这样做。

Python 递归 矩阵 语言不可知

评论

0赞 Saba 12/20/2021
@martineau我确实解决了 2x2 的问题,但同样的算法对其他人不起作用,所以我认为它不会真正帮助任何事情。
0赞 ToolmakerSteve 12/20/2021
我认为计算机科学 stackexchange 更适合获得算法帮助。
1赞 ToolmakerSteve 12/20/2021
我投票关闭这个问题,因为它属于 cs.stackexchange.com。(我想,如果我错了,有人会纠正我。
1赞 Scott Hunter 12/20/2021
您可能需要考虑学习如何编写生成器;随着矩阵和/或数字列表变大,组合的数量可能会变得非常大。
0赞 martineau 12/20/2021
在这种情况下,你需要帮助扩展你的算法,那么你至少应该用文字更彻底地解释/描述它是如何工作的,而不仅仅是发布它的代码。我也同意@ToolmakerSteve的观点,即您的问题更适合 Computer Science Stack Exchange,因为它本身并不是真正的 Python。

答:

0赞 Stef 12/21/2021 #1

这是一种可能性:

  • 使用 和 生成所有可能的矩阵itertools.permutationsnumpy.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]]

文档:

0赞 Saba 12/21/2021 #2

通过添加一个检查每 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