给定一个Nside平方矩阵,有没有不使用循环或if条件的方法来求单元的环值?

2024-09-28 05:16:42 发布

您现在位置:Python中文网/ 问答频道 /正文

例如,假设你有一个6边的正方形矩阵。 这些是笛卡尔指数:

(0,0) (0,1) (0,2) (0,3) (0,4) (0,5)
(1,0) (1,1) (1,2) (1,3) (1,4) (1,5)
(2,0) (2,1) (2,2) (2,3) (2,4) (2,5)
(3,0) (3,1) (3,2) (3,3) (3,4) (3,5)
(4,0) (4,1) (4,2) (4,3) (4,4) (4,5)
(5,0) (5,1) (5,2) (5,3) (5,4) (5,5)

6边正方形有3个环:A

A A A A A A
A B B B B A
A B C C B A
A B C C B A
A B B B B A
A A A A A A

问题什么函数可以获取单元格的坐标,即正方形的N边,并相应地返回环值?例如:

f(x = 1, y  2, N = 6) = B

A,B,C。。。可以是任何数值:1、2、3。。。或0,1,2。。。或者别的什么。重要的是它们对任何N都是一致的。例如:

N = 1   =>   A = 1
N = 2   =>   A = 1
N = 3   =>   A = 1, B = 2
N = 4   =>   A = 1, B = 2
N = 5   =>   A = 1, B = 2, C = 3
N = 6   =>   A = 1, B = 2, C = 3
N = 7   =>   A = 1, B = 2, C = 4, D = 4
...

使用if条件问题很容易解决。 给定一对(x,y)和正方形边N:

# N//2 is the number of rings in a N-side square
for k in range(1,N//2+1):
    if x == 0+k-1 or y== 0+k-1 or x == N-k or y == N-1:
        return k

不过,这似乎是一种非常昂贵的方法来寻找细胞的环值。 我试着用对角线,坐标和,坐标差来求函数。。。但我还是什么也没找到。 有人遇到过这个问题吗? 有办法解决吗


Tags: orofthe函数innumberifis
3条回答

看起来像是要解决的数学问题。 编辑:更新了功能,应该可以更好的处理奇偶点后的中点情况。然而,OP的要求是把它变成一个数学方程,我不知道怎么做

import math


def ring_finder(x, y, N, outer_ring = 0):
    '''
    x and y are the coordinates of a cell, N is the length of the side of square
    Returns the correct ring count starting from outer_ring value (default, 0)
    '''
    if x >= N or y >= N:
        print("coordinates outside square, please check")
        return None
    no_of_squares = math.ceil(N/2)
    x = N - x - 1 if x >= no_of_squares else x
    y = N - y - 1 if y >= no_of_squares else y
    return min(x, y) + outer_ring

环形探测器(5、5、6)

ring_finder(1, 2, 6)

我认为这个函数满足您的要求:

def ring_id(n, i, j):
    even = n % 2 == 0
    n_2 = n // 2
    i = i - n_2
    if even and i >= 0:
        i += 1
    i = abs(i)
    j = j - n_2
    if even and j >= 0:
        j += 1
    j = abs(j)
    ring_id = i + max(j - i, 0)
    return n_2 - ring_id

字母小测验:

import string

def print_rings(n):
    ring_names = string.ascii_uppercase
    for i in range(n):
        for j in range(n):
            rid = ring_id(n, i, j)
            print(ring_names[rid], end=' ')
        print()

print_rings(6)
# A A A A A A
# A B B B B A
# A B C C B A
# A B C C B A
# A B B B B A
# A A A A A A
print_rings(7)
# A A A A A A A
# A B B B B B A
# A B C C C B A
# A B C D C B A
# A B C C C B A
# A B B B B B A
# A A A A A A A

编辑:如果您坚持不在函数中使用if这个词,您可以(有些尴尬地)将上述函数重写为:

def ring_id(n, i, j):
    even = 1 - n % 2
    n_2 = n // 2
    i = i - n_2
    i += even * (i >= 0)
    i = abs(i)
    j = j - n_2
    j += even * (j >= 0)
    j = abs(j)
    ring_id = i + max(j - i, 0)
    return n_2 - ring_id

或者,如果你想让它看起来更像“公式”(尽管不可读,而且需要更多的重复计算):

def ring_id(n, i, j):
    i2 = abs(i - (n // 2) + (1 - n % 2) * (i >= (n // 2)))
    j2 = abs(j - (n // 2) + (1 - n % 2) * (j >= (n // 2)))
    return (n // 2) - i2 + max(j2 - i2, 0)

虽然这或多或少不是“数学”的,但基本上是相同的逻辑

在“无穷范数”意义上,环值是到数组中心距离的补码

N/2 - max(|X - (N-1)/2|, |Y - (N-1)/2|).

这为A赋值0,为B赋值1,依此类推

为了避免半整数,可以使用

(N - min(|2X - N + 1|, |2Y - N + 1|) / 2.

maxabs函数可能涉及隐藏的ifs,但您无法避免


def Ring(X, Y, N):
    return (N - max(abs(2 * X - N + 1), abs(2 * Y - N + 1))) // 2

for N in range(1, 8):
    for X in range(N):
        for Y in range(N):
            print(chr(Ring(X, Y, N) + 65), '', end= '')
        print()
    print()

A 

A A 
A A 

A A A 
A B A 
A A A 

A A A A 
A B B A 
A B B A 
A A A A 

A A A A A 
A B B B A 
A B C B A 
A B B B A 
A A A A A 

A A A A A A 
A B B B B A 
A B C C B A 
A B C C B A 
A B B B B A 
A A A A A A 

A A A A A A A 
A B B B B B A 
A B C C C B A 
A B C D C B A 
A B C C C B A 
A B B B B B A 
A A A A A A A 

相关问题 更多 >

    热门问题