有一个由数字0-9组成的n*n矩阵.例如:

6 0 0 8 9 6 1 
5 1 6 8 1 1 0 
4 2 1 3 7 1 5 
8 8 6 6 2 5 2 
7 9 4 6 9 6 4 
1 4 7 8 5 3 8 
9 4 8 3 9 2 9

我需要找到要更改的最小数量的数字(在矩阵内),以使其一次关于多行(/、\、-、|)对称.

我 for each 对称(/、\、-、|)做了四个函数.他们列出了两个需要具有相同值的数字的列表.这些函数如下所示:

import math
"""lenght = how many numbers in one line"""

def symmetry_horizontaln(lenght):
    for i in range(math.ceil(lenght/2)):
        for j in range(lenght):
            round_result = []
            round_result.append((i, j))
            round_result.append((lenght-i-1, j))

def symmetry_vertical(lenght):
    for i in range(lenght):
        for j in range(lenght):
            if j < math.ceil(lenght/2):
                round_result= []
                round_result.append((i, j))
                round_result.append((i, lenght-j-1))
    
def symmetry_main_diagonal(lenght):
    for i in range(lenght):
        for j in range(lenght):
            if j <= i:
                   round_result= []
                   round_result.append((i, j))
                   round_result.append((j, i))

def symmetry_second_diagonal(lenght): 
    for i in range(lenght):
        for j in range(lenght):
            if j <= lenght-i-1:
                   round_result= []
                   round_result.append((i, j))
                   round_result.append((lenght-j-1, lenght-i-1))

现在我需要以某种方式将舍入结果放在一起,这样我就可以获得矩阵中需要具有相同值的点的列表.例如,如果有这样的矩阵:

6 0 0 8 9 6 1 
5 1 6 8 1 1 0 
4 2 1 3 7 1 5 
8 8 6 6 2 5 2 
7 9 4 6 9 6 4 
1 4 7 8 5 3 8 
9 4 8 3 9 2 9

它需要对这些行进行整合:-和/,最终的列表将如下所示:

[[(6, 2), (4, 0), (0, 4), (4, 6), (2, 0), (6, 4), (0, 2), (2, 6)], [(2, 3), (3, 2), (3, 4), (4, 3)], [(3, 1), (5, 3), (1, 3), (3, 5)], [(1, 2), (2, 1), (5, 4), (1, 4), (4, 5), (2, 5), (4, 1), (5, 2)], [(1, 1), (5, 5), (5, 1), (1, 5)], [(0, 1), (6, 5), (6, 1), (5, 0), (5, 6), (0, 5), (1, 0), (1, 6)], [(4, 4), (2, 4), (4, 2), (2, 2)], [(6, 3), (0, 3), (3, 6), (3, 0)], [(3, 3)], [(6, 6), (6, 0), (0, 6), (0, 0)]]

从这个列表中,我知道如何更改最小数量的数字,以使I关于这些线对称.我想现在是30岁.但我不知道怎么才能拿到那份名单.

这就是我try 过的:

我对前面的函数进行了如下修改(每个函数的最后两行都是新的):

def symmetry_horizontaln(lenght):
    for i in range(math.ceil(lenght/2)):
        for j in range(lenght):
            round_result = []
            round_result.append((i, j))
            round_result.append((lenght-i-1, j))
              
            function((i, j), round_result)
            function((delka-i-1, j), round_result)

def symetry_horizontal(lenght):
    ...
    function((i, j), round_result)
    function((i, lenght-j-1), round_result)

...

并制作了一个新函数来获取最终列表:

x = []

def function(point, round_result):
    if round_result[0] == round_result[1]:
        round_result = list(set(round_result))

    if not x:
        x.append(round_result)
    else:
        for i in x:
            if i == round_result:
                pass
            elif point in i:
                i.append(round_result[0])
                i.append(round_result[1])
            else:
                x.append(round_result)
                break

print(x)

但这似乎行不通.如有任何帮助,我们不胜感激!

推荐答案

您可以try 以下操作:

import numpy as np
import scipy

a = np.array([[6, 0, 0, 8, 9, 6, 1],
              [5, 1, 6, 8, 1, 1, 0],
              [4, 2, 1, 3, 7, 1, 5],
              [8, 8, 6, 6, 2, 5, 2],
              [7, 9, 4, 6, 9, 6, 4],
              [1, 4, 7, 8, 5, 3, 8],
              [9, 4, 8, 3, 9, 2, 9]])

def symm(a, pattern="hvdc"):
    b = np.stack([np.rot90(a, k=i) for i in range(4)])
    b = np.concatenate([b, b.swapaxes(1, 2)])
    subgps = {frozenset(s) : [0, i]  for i, s in enumerate("dvch", 4)}
    subgps |= {frozenset("vh"): [0, 2, 5, 7], frozenset("dc"): [0, 2, 4, 6]}
    if (p := frozenset(pattern)) in subgps:
        b = b[subgps[p]] 
    return scipy.stats.mode(b, keepdims=False)[0]

此函数返回具有所有指定对称性的矩阵:h=水平、v=垂直、d=对角线(即\)、c=交叉对角线(即/).字符-|/\作为函数自变量并不方便,因为例如"\"不是有效的Python字符串.

例如,要获得一个关于两条对角线对称的矩阵,可以使用

print(symm(a, "dc"))

这提供了:

[[6 0 4 8 5 0 1]
 [0 1 6 8 1 1 0]
 [4 6 1 6 4 1 5]
 [8 8 6 6 6 8 8]
 [5 1 4 6 1 6 4]
 [0 1 1 8 6 1 0]
 [1 0 5 8 4 0 6]]

以这种方式获得的对称化矩阵具有改变的最小条目数量.这样的矩阵不是唯一的,因为在某些地方可能会 Select 使用哪个数字.然后,用户可以判断有多少条目被更改:

print((a != symm(a, "dc")).sum())

它提供了:

26

具有在对称化后将具有相同值的条目的坐标的列表可以如下获得(在本例中,对于"dc"个对称,即关于两条对角线):

n = a.shape[0]
b = symm(np.arange(n**2).reshape(n, n), "dc")
orbits = [list(zip(*np.where(b == i))) for i in np.unique(b)]

for c in orbits:
    print(c)

这提供了:

[(0, 0), (6, 6)]
[(0, 1), (1, 0), (5, 6), (6, 5)]
[(0, 2), (2, 0), (4, 6), (6, 4)]
[(0, 3), (3, 0), (3, 6), (6, 3)]
[(0, 4), (2, 6), (4, 0), (6, 2)]
[(0, 5), (1, 6), (5, 0), (6, 1)]
[(0, 6), (6, 0)]
[(1, 1), (5, 5)]
[(1, 2), (2, 1), (4, 5), (5, 4)]
[(1, 3), (3, 1), (3, 5), (5, 3)]
[(1, 4), (2, 5), (4, 1), (5, 2)]
[(1, 5), (5, 1)]
[(2, 2), (4, 4)]
[(2, 3), (3, 2), (3, 4), (4, 3)]
[(2, 4), (4, 2)]
[(3, 3)]

Python相关问答推荐

巨 Python :逆向猜谜游戏

处理Gekko的非最优解

在numpy数组中寻找楼梯状 struct

如何过滤组s最大和最小行使用`transform`'

如何在GEKKO中使用复共轭物

需要帮助使用Python中的Google的People API更新联系人的多个字段'

浏览超过10k页获取数据,解析:欧洲搜索服务:从欧盟站点收集机会的微小刮刀&

将多行数据循环到嵌套框架中的单行

Antlr Python错误处理简单的PLSQL

通过PyTorch中的MIN函数传递渐变

如何在保持sibling 姐妹美汤的同时插入和删除标签?

基于符号和位置 Select 数据帧特定区域的毕达式方法

如何使用Tkinter的CheckButtom隐藏或显示由滑块控制的画布线?

Regex模式在Python中不起作用,但在RegExr上?

极点:AWS S3连接池

如何验证像这样添加的对象属性:MyObj.newattribute=123

最小大小的子数组和结束条件出了什么问题

从html获取元素时出现问题

无法调用Python文档对象

解析类型的字符串表示形式以获取子项的类型