Math 将正方形放置在笛卡尔平面上,并根据序列号计算出它们的X,Y坐标

Math 将正方形放置在笛卡尔平面上,并根据序列号计算出它们的X,Y坐标,math,sequence,discrete-mathematics,cartesian,Math,Sequence,Discrete Mathematics,Cartesian,我和一群同事都在努力解决这个问题,但却找不到一个干净有效的数学方法来解决这个问题。这是: 给定一个标准的笛卡尔平面和一系列图像(都是正方形,尺寸相同,例如,我们只说1个单位),我们如何组织它们,使它们通过左上角围绕平面原点(0,0)旋转。但更具体地说,如果给定数字25(序列中的第25个正方形),它的X,Y坐标是多少 希望这张粗糙的图像有助于解释这个序列。第一个放在网格上的正方形是红色,然后是蓝色、黄色、紫色、绿色、黑色、棕色,然后是圆点所示的周围 我们希望有一个“相对”简单的数学公式,但这可能

我和一群同事都在努力解决这个问题,但却找不到一个干净有效的数学方法来解决这个问题。这是:

给定一个标准的笛卡尔平面和一系列图像(都是正方形,尺寸相同,例如,我们只说1个单位),我们如何组织它们,使它们通过左上角围绕平面原点(0,0)旋转。但更具体地说,如果给定数字25(序列中的第25个正方形),它的X,Y坐标是多少

希望这张粗糙的图像有助于解释这个序列。第一个放在网格上的正方形是红色,然后是蓝色、黄色、紫色、绿色、黑色、棕色,然后是圆点所示的周围


我们希望有一个“相对”简单的数学公式,但这可能是一厢情愿的想法。

假设您使用基于1的索引,您可以使用以下算法来找到答案(不确定是否存在封闭形式的解决方案)

这背后的想法是找出你在哪一层(你的x或y离0有多远)。然后找出你所在的象限。然后算出你在哪一边,然后算出坐标

get_coords(n)
    layer = 1
    while (n > 3 * layer * layer + (layer+1)*(layer+1))
        ++layer
    layer_ind = n - 3 * (layer - 1) * (layer - 1) - layer * layer
    if (layer_ind < 2 * layer + 1) # in bottom right
        if (layer_ind <= layer + 1)
            return (layer, - layer_ind + 1)
        else
            return (2 * layer + 1 - layer_ind, -layer)
    else if ((layer_ind - 2 * layer - 1)/(2 * layer - 1) < 1) # bottom left
        layer_ind = layer_ind - 2 * layer - 1
        if (layer_ind <= layer)
            return (-layer_ind+1, -layer+1)
        else
            return (-layer+1, -2*layer + 1 + layer_ind)
    else if ((layer_ind - 2 * layer - 1)/(2 * layer - 1) < 2) # top left
        layer_ind = layer_ind - 4 * layer
        if (layer_ind <= layer)
            return (-layer+1, layer_ind)
        else
            return (layer_ind - 2 * layer, layer)
    else # top right
        layer_ind = layer_ind - 6 * layer + 1
        if (layer_ind <= layer)
            return (layer_ind-1, layer)
        else
            return (layer-1, 2 * layer - layer_ind)
获取坐标(n)
层=1
而(n>3*层*层+(层+1)*(层+1))
++层
层索引=n-3*(层-1)*(层-1)-层*层
如果(层索引<2*层+1)#在右下角
如果(layer_ind我以前的答案(现在降级到修订历史)是一个递归解决方案。下面是我所说的“循环”解决方案

我们的想法是围绕一个正方形旋转多次。在任何给定的指数下:

  • 我们正在围绕一个较小的广场进行一场革命
  • 我们在这个广场的一边
  • 我们在广场的一边
通过跟踪正方形、侧面和侧面下方的距离,我们可以索引每个点

我们画一条正方形,画4条等边线(称之为“段”)。在第一段中间开始每一次旋转。< /P> 例如:

旋转1围绕大小为0的正方形,长度为1的线段:

            O    OO
 O    OO    OO   OO
旋转2围绕一个大小为4的正方形,长度为3的线段:

            O     OOOO  OOOO 
 OO    OO   OOO   OOO   OOOO
 OOO   OOO  OOOO  OOOO  OOOO
   O  OOOO  OOOO  OOOO  OOOO
公转3围绕一个大小为16的正方形,长度为5的线段:

                 O       OOOOOO  OOOOOO
 OOOO    OOOO    OOOOO   OOOOO   OOOOOO
 OOOO    OOOO    OOOOO   OOOOO   OOOOOO
 OOOOO   OOOOO   OOOOOO  OOOOOO  OOOOOO
 OOOOO   OOOOO   OOOOOO  OOOOOO  OOOOOO
     O  OOOOOO   OOOOOO  OOOOOO  OOOOOO
下面是Python的一个实现

import math

def makeSquare(main_index, offset_size):
    step_index = int(math.sqrt(main_index))/2   # How many revolutions have we made?
    last_square = int(math.pow(step_index*2,2)) # Whats the largest square less than main_index?
    segment_length = (2 * step_index) + 1       # How long is the side of the square we've made so far? The segment length is 1 more than that.

    main_index = main_index + step_index + 1    # Skip ahead so we start in the middle of the right side instead of the top. We do some modulo stuff below to wrap around.

    segment_index = (main_index - last_square) / segment_length # Which segment are we on?
    dot_index = main_index - segment_index*segment_length - last_square # How far along the segment are we?

    draw_functions = [
        lambda i, size:  [size,     size - i], # Draw the right side of a square
        lambda i, size:  [size - i, 0       ], # Draw the bottom of a square
        lambda i, size:  [0,        i       ], # Draw the left side of a square
        lambda i, size:  [i,        size    ], # Draw the top of a square
    ]    

    x, y = draw_functions[segment_index % 4](dot_index % (4 * segment_length), segment_length)
    return [ x + offset_size - step_index - 1, y + offset_size - step_index - 1]

# Print the points to the console in sequence
import time, os
step = 4
points = [makeSquare(i, step) for i in range(int(math.pow(step*2,2)))]
board = [[" " for x in range(step*2)] for x in range(step*2)] 
for p in range(len(points)):
    print
    print p, "------------------"
    board[step*2-1 - points[p][1]][points[p][0]] = "O" # Do some coordinate wrangling so we have normal X and Y
    print (os.linesep).join([''.join(row) for row in board])
    time.sleep(.1)
(编辑时:我添加了第二个函数,可以直接获得笛卡尔坐标版本。)

在我的脑袋爆炸之前,我就知道了。它是封闭形式,在某种意义上,它给出了第一百万个正方形的坐标,而不需要将它们逐个放在一个循环中。写下它不会给出一个很好的公式,但你可以写为一个分片定义的公式,有8个部分。答案是在基于1的网格坐标中给出的。t第一个坐标告诉你在y轴的右边或左边有多少个正方形,第二个坐标告诉你向上或向下有多远。从这些数字可以相对容易地得到它们左上角的笛卡尔坐标。我用Python实现了它:

from math import sqrt, ceil

def coordinates(m):
    n = ceil(sqrt(m)/2) #shell number
    i = m - 4*(n-1)**2 #index in shell
    if i <= n:
        return (n,-i)
    elif i <= 2*n-1:
        return (2*n - i, -n)
    elif i <= 3*n - 1:
        return (2*n - 1 - i, -n)
    elif i <= 4*n - 2:
        return (-n, -4*n + 1  + i)
    elif i <= 5*n - 2:
        return (-n, -4*n + 2 + i)
    elif i <= 6*n - 3:
        return (-6*n + 2 + i, n)
    elif i <= 7*n - 3:
        return (-6*n + 3 + i,n)
    else:
        return (n, 8*n -3 - i)
如果你想知道:

>>> coordinates(1000000)
(500, 1)
最后一个答案是有意义的,因为第一百万个正方形是1000x1000个正方形网格的顶点

我使用上述方法在tkinter画布小部件上放置彩色方块:


你应该列出顺序。我假设所有的正方形都是围绕原点的第一个螺旋,点是第二个?你所说的坐标是什么意思?正方形的中心?左角?例如--你会给黑色正方形指定什么数字?(2,-2)?@r3两条注释:1)你应该用你计划用来实现你的解决方案的编程语言来标记这个问题,2)你应该回顾一下下面给出的经过深思熟虑的答案。正方形的坐标分别对应于它们的左上角,因此在示例图像中,黑色正方形将位于(1,-1)。至于编程语言,假设答案不使用该语言独有的库,任何语言解决方案都足够了。翻译成其他语言很容易。但具体来说,这将在PHP中实现。我将在明天早上与其他人一起回顾所有给出的答案,然后标记出最佳解决方案,它们看起来都很棒。所有答案都经过深思熟虑并具有建设性,但您的答案是最优雅的,用最少的代码解决了我们遇到的问题,做得很好!
def  cartCoordinates(m):
    n = ceil(sqrt(m)/2) #shell number
    i = m - 4*(n-1)**2 #index in shell
    if i <= n:
        return (n-1,-i+1)
    elif i <= 3*n - 1:
        return (2*n - 1 - i, -n + 1)
    elif i <= (5*n - 2):
        return (-n, -4*n + 2 + i)
    elif i <= 7*n - 3:
        return (-6*n + 2 + i, n)
    else:
        return (n-1, 8 * n - 3 - i)
>>> for n in range(1,17):
    print(n, ': grid coords =', coordinates(n),
          'Cartesian =',cartesianFromGrid(*coordinates(n)))


1 : grid coords = (1, -1) Cartesian = (0, 0)
2 : grid coords = (-1, -1) Cartesian = (-1, 0)
3 : grid coords = (-1, 1) Cartesian = (-1, 1)
4 : grid coords = (1, 1) Cartesian = (0, 1)
5 : grid coords = (2, -1) Cartesian = (1, 0)
6 : grid coords = (2, -2) Cartesian = (1, -1)
7 : grid coords = (1, -2) Cartesian = (0, -1)
8 : grid coords = (-1, -2) Cartesian = (-1, -1)
9 : grid coords = (-2, -2) Cartesian = (-2, -1)
10 : grid coords = (-2, -1) Cartesian = (-2, 0)
11 : grid coords = (-2, 1) Cartesian = (-2, 1)
12 : grid coords = (-2, 2) Cartesian = (-2, 2)
13 : grid coords = (-1, 2) Cartesian = (-1, 2)
14 : grid coords = (1, 2) Cartesian = (0, 2)
15 : grid coords = (2, 2) Cartesian = (1, 2)
16 : grid coords = (2, 1) Cartesian = (1, 1)
>>> coordinates(1000000)
(500, 1)