如何获得半幻方?

huangapple go评论86阅读模式
英文:

How I can get semimagic square?

问题

你的问题是你的程序修改了输入矩阵中已有的数字,而你希望它只修改点(.)。你可以通过修改你的代码来解决这个问题。在SimpleMatrix函数中,你可以添加一个条件来检查是否应该在当前位置插入数字。这里是修改后的代码:

def SimpleMatrix(number, row, colum, size):
    """
    Distribution of the matrix by elements, for example
    our matrix:
     [2 2 5]
     [. . 0]
     [1 . .]
     for 2 in (0,0) => [2 0 0]
                       [0 2 0]
                       [0 0 2]
    for 2 in (0,1) =>  [2 3 0]
                       [0 2 0]
                       [0 0 2]
    """
    matrix = [[0 for _ in range(size)] for _ in range(size)]
    
    if matrix[row][colum] == 0:  # Only insert if the current position is empty
        matrix[row][colum] = number

    for i in range(size):
        for j in range(size):
            if not (i == row or j == colum) and matrix[i][j] == 0 and RowAndColumEmpty(matrix, i, j):
                matrix[i][j] = number
                break

    return matrix

通过这个修改,你的程序将只在当前位置为空(值为0)的情况下插入数字,而不会覆盖已经存在的数字。这应该解决了你的问题。

英文:

How do I implement this in Python?

> Given is an input matrix like this one:
>
>
> ┌───┬───┬───┐
> │ 2 │ 2 │ 5 │
> ├───┼───┼───┤
> │ . │ . │ 0 │
> ├───┼───┼───┤
> │ 3 │ . │ . │
> └───┴───┴───┘
>

> Instead of dots, insert numbers so that the sum of the numbers in the rows and columns in the square is the same.

My code:

def EnterMatr():
    matr = []

    n = int(input("Enter n: "))

    print("Enter a matrix:")
    for i in range(n):
        arr = input().split()
        for j in range(len(arr)):
            if arr[j] == ".": # Dots are replaced by None
                arr[j] = None
            else:
                arr[j] = int(arr[j])
        matr.append(arr)

    return matr
    
def SimpleMatrix(number, row, colum, size):
    """
    Distribution of the matrix by elements, for example
    our matrix:
     [2 2 5]
     [. . 0]
     [1 . .]
     for 2 in (0,0) => [2 0 0]
                       [0 2 0]
                       [0 0 2]
    for 2 in (0,1) =>  [0 2 0]
                       [2 0 0]
                       [0 0 2]
    """
    matrix = [[0 for _ in range(size)] for _ in range(size)]
    matrix[row][colum] = number

    for i in range(size):
        for j in range(size):
            if not (i == row or j == colum) and RowAndColumEmpty(matrix, i, j):
                matrix[i][j] = number
                break

    return matrix

def GenerateMultiSemiMetrix(matr):
    MultiMatrix = []

    for i in range(len(matr)):
        for j in range(len(matr)):
            if matr[i][j]:
                MultiMatrix.append(SimpleMatrix(matr[i][j], i,j,len(matr)))
    return MultiMatrix

def RowAndColumEmpty(matr, row, colum):
    """
    Checking whether the row and column where we insert are empty
    """
    for i in range(len(matr)):
        if not matr[row][i] == 0:
            return False
    for i in range(len(matr)):
        if not matr[i][colum] == 0:
            return False
    return True

def addMatr(first, second):
    matrix = [[0 for _ in range(len(first))] for _ in range(len(first))]

    for i in range(len(first)):
        for j in range(len(first)):
            matrix[i][j] = first[i][j] + second[i][j]
    return matrix

def SumMatrix(MatrArr):
    matrix = [[0 for _ in range(len(MatrArr[0]))] for _ in range(len(MatrArr[0]))]
    
    for elem in MatrArr:
        matrix = addMatr(matrix, elem)
    return matrix




matr = EnterMatr()
matr = SumMatrix(GenerateMultiSemiMetrix(matr))
for elem in matr:
    print(elem)

Here is the output of an execution of that code:

Enter n: 3
Enter a matrix:
2 2 5
. . 0
1 . .
[2, 3, 5]
[7, 2, 1]
[1, 5, 4]

The problem is that the result matrix has different numbers at places where already numbers were given in the input matrix:

  • The original 2 at (0, 1) becomes 3
  • The original 0 at (1, 2) becomes 1

This should not be possible.

How can I change the program such that it would only change the dots?

Is there any algorithm or something else that could solve my problem?

答案1

得分: 0

这可以表示为𝑛²矩阵的一组方程式以及求和变量的集合。然后剩下的是解决这组线性方程式。您可以使用a package来解决这个问题。

这里我实现了Guassian elimination方法:

def gaussian_elimination(table):
    height = len(table)
    width = len(table[0])
    h = 0
    for x in range(width):
        abspivot = max(abs(table[y][x]) for y in range(h, height))
        if abspivot:
            pivoty = next(y for y in range(h, height) if abs(table[y][x]) == abspivot)
            pivotrow = table[pivoty]
            pivot = pivotrow[x]
            table[h], table[pivoty] = pivotrow, table[h]  # swap rows
            for j in range(x, width):  # divide pivot row to get a 1
                pivotrow[j] /= pivot
            for y, row in enumerate(table):  # subtract pivotrow from other rows
                if y != h:
                    coeff = row[x]
                    row[x] = 0
                    for j in range(x + 1, width):
                        row[j] -= coeff * pivotrow[j] 
            h += 1
            if h >= height:
                break
    # 从表中提取解决的值
    values = [0] * (width - 1)
    for row in table:
        for i in range(width - 1):
            if row[i]:
                values[i] = row[-1]
                break
    return values
        
    
def solve(matr):
    width = len(matr)
    size = width * width
    # 创建表示方程式的扩展矩阵
    table = []
    # 添加方程式以反映行的总和
    for y in range(width):
        eq = [0] * (size + 2)
        eq[y * width:(y+1) * width] = [1] * width
        eq[size] = -1
        table.append(eq)
    # 添加方程式以反映列的总和
    for x in range(width):
        eq = [0] * (size + 2)
        for i in range(x, size, width):
            eq[i] = 1
        eq[size] = -1
        table.append(eq)
    # 添加方程式以反映已知值
    for y, row in enumerate(matr):
        for x, val in enumerate(row):
            if val is not None:
                eq = [0] * (size + 2)
                eq[y * width + x] = 1
                eq[-1] = val
                table.append(eq)
    # 使用高斯消元法解决这组方程式
    values = gaussian_elimination(table)
    # 验证所有解决的值都是整数
    if any(val - int(val) for val in values):
        raise ValueError("解决方案中出现意外的非整数")
    values = list(map(int, values))
    # 将值转换回矩阵
    return [ 
        values[width * y: width * (y + 1)]
        for y in range(width)
    ]
    
matr = [
    [2, 2, 5],
    [None, None, 0],
    [1, None, None]
]
print(solve(matr))

这将输出:

[[2, 2, 5], [6, 3, 0], [1, 4, 4]]
英文:

This can be represented as a set of equations on the 𝑛² variables of the 𝑛x𝑛 matrix and a variable for the sum. Then remains to solve this set of linear equations. You can use a package for that.

Here I have implemented the Guassian elimination method:

def gaussian_elimination(table):
height = len(table)
width = len(table[0])
h = 0
for x in range(width):
abspivot = max(abs(table[y][x]) for y in range(h, height))
if abspivot:
pivoty = next(y for y in range(h, height) if abs(table[y][x]) == abspivot)
pivotrow = table[pivoty]
pivot = pivotrow[x]
table[h], table[pivoty] = pivotrow, table[h]  # swap rows
for j in range(x, width):  # divide pivot row to get a 1
pivotrow[j] /= pivot
for y, row in enumerate(table):  # subtract pivotrow from other rows
if y != h:
coeff = row[x]
row[x] = 0
for j in range(x + 1, width):
row[j] -= coeff * pivotrow[j] 
h += 1
if h >= height:
break
# Extract the resolved values from the table
values = [0] * (width - 1)
for row in table:
for i in range(width - 1):
if row[i]:
values[i] = row[-1]
break
return values
def solve(matr):
width = len(matr)
size = width * width
# Create an augemented matrix representing equations
table = []
# Add equations to reflect sum of rows
for y in range(width):
eq = [0] * (size + 2)
eq[y * width:(y+1) * width] = [1] * width
eq[size] = -1
table.append(eq)
# Add equations to reflect sum of columns
for x in range(width):
eq = [0] * (size + 2)
for i in range(x, size, width):
eq[i] = 1
eq[size] = -1
table.append(eq)
# Add equations to reflect the known values
for y, row in enumerate(matr):
for x, val in enumerate(row):
if val is not None:
eq = [0] * (size + 2)
eq[y * width + x] = 1
eq[-1] = val
table.append(eq)
# Solve this set of equations with the Gaussian elimination method
values = gaussian_elimination(table)
# Verify that all resolved values are integers
if any(val - int(val) for val in values):
raise ValueError("Unexpected non-integer in solution")
values = list(map(int, values))
# Turn the values back into a matrix
return [ 
values[width * y: width * (y + 1)]
for y in range(width)
]
matr = [
[2, 2, 5],
[None, None, 0],
[1, None, None]
]
print(solve(matr))

This outputs:

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

huangapple
  • 本文由 发表于 2023年5月20日 20:21:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/76295209.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定