Algorithm 从位置获取螺旋索引

Algorithm 从位置获取螺旋索引,algorithm,language-agnostic,Algorithm,Language Agnostic,我使用阿尔贝托·桑蒂尼对这个问题的解决方案,得到一个基于项目索引的螺旋网格参考 这不是公认的解决方案,但它最适合我的需要,因为它避免了使用循环 它工作得很好,但我现在想做的是做相反的事情。基于已知的x和y坐标返回位置的索引 这是返回给定位置周围的项目的前提。我不知道是否有一个简明的数学公式来推导您想要的内容,但我有一个解决方案,可以在每次查询的O(1)时间内计算您想要的内容。没有你想要的循环 我的做法: (i) 对于任何给定点(x,y),找出位于边长平方(2*a-1)内的点的数量,其中a=Ma

我使用阿尔贝托·桑蒂尼对这个问题的解决方案,得到一个基于项目索引的螺旋网格参考

这不是公认的解决方案,但它最适合我的需要,因为它避免了使用循环

它工作得很好,但我现在想做的是做相反的事情。基于已知的x和y坐标返回位置的索引


这是返回给定位置周围的项目的前提。

我不知道是否有一个简明的数学公式来推导您想要的内容,但我有一个解决方案,可以在每次查询的O(1)时间内计算您想要的内容。没有你想要的循环

我的做法:

(i) 对于任何给定点(x,y),找出位于边长平方(2*a-1)内的点的数量,其中a=Max(| x |,| y |)。这些是内部要点。i、 e,不包括当前缓和曲线在内的所有缓和曲线中的点数

这只不过是(2*a-1)*(2*a-1)

EG:考虑下面的图表:

y
          |
          |
   16 15 14 13 12
   17  4  3  2 11
-- 18  5  0  1 10 --- x
   19  6  7  8  9
   20 21 22 23 24
          |
          |
对于点(2,1),a=2。内部点在这里标记为0、1、2、3、4、5、6、7、8-边长为3的正方形

(ii)现在计算当前缓和曲线上的点。缓和曲线有4个“角点”——

(a) 起点(当前缓和曲线的起点)

(b) 重点(a,a)

(c) 点(-a,a)

(d) 点(-a,-a)

因此,我计算每一对之间的元素数量[即,(a)和(b),(b)和(c),(c)和(d)],所有这些元素都落在螺旋序列中所需的输入点之前。这可以通过简单地减去点坐标来实现

该值加上内部点数将为您提供所需答案

我不知道我是否解释得很清楚。如果您需要任何澄清或进一步解释,请务必告诉我

附件是我为测试逻辑而编写的JAVA代码。很抱歉,它不是很优雅,但很有效:P

import java.io.IOException;
import java.util.Scanner;

class Pnt
{
    int x, y;

    public Pnt( int _x, int _y )
    {
        x = _x;
        y = _y;
    }
}

public class Spiral
{

    static int interior( Pnt p ) // returns points within interior square of side length MAX( x, y ) - 1
    {
        int a = Math.max( Math.abs( p.x ), Math.abs( p.y ));
        return ( 2*a - 1 )*( 2*a - 1 );
    }


    static Pnt startPnt( Pnt p ) // first point in that spiral
    {
        int a = Math.max( Math.abs( p.x ), Math.abs( p.y ));

        // last pnt in prev spiral = [ a-1, -( a-1 ) ]

        // next pnt  = [ a, -( a-1 ) ]

        return new Pnt( a, -( a-1 ));
    }

    static int offSetRow1( Pnt pStart, Pnt p )
    {

        return ( p.y - pStart.y ) + 1;
    }



    static int solve( Pnt curr )
    {
        // check location of curr
        // It may lie on 1st row, 2nd row, 3rd or 4th row

        int a = Math.max( Math.abs( curr.x ), Math.abs( curr.y ));
        int off=0;
        int interiorCnt = interior( curr );
        Pnt start = startPnt( curr );

        if( ( curr.x == a ) && ( curr.y >= start.y ) ) // row 1
        {
            off = offSetRow1( start, curr );
            return off+interiorCnt;
        }

         if( curr.y == a ) // row 2
        {
            Pnt start2 = new Pnt( a, a );
            int off1 = offSetRow1( start, start2 );

            // now add diff in x-coordinates

            int off2 = start2.x - curr.x;
            off = off1 + off2;
            return off+interiorCnt;

        }

        if( curr.x == -a ) // row 3
        {
            Pnt start2 = new Pnt( a, a );
            int off1 = offSetRow1( start, start2 );

            // now add diff in x-coordinates

            Pnt start3 = new Pnt( -a, a );
            int off2 = start2.x - start3.x;

            // now add diff in y co-ordinates


            int off3 = start3.y - curr.y;

            off = off1 + off2 + off3;
            return off+interiorCnt;

        }

        else // row 4
        {
             Pnt start2 = new Pnt( a, a );
            int off1 = offSetRow1( start, start2 );

            // now add diff in x-coordinates

            Pnt start3 = new Pnt( -a, a );
            int off2 = start2.x - start3.x;

            // now add diff in y co-ordinates


            int off3 = start3.y - curr.y;

            Pnt start4 = new Pnt( -a, -a );

            // add diff in x co-ordinates

            int off4 = curr.x - start4.x;
            off = off1 + off2 + off3 + off4;
            return interiorCnt + off;
        }


    }

    public static void main( String[] args ) throws IOException
    {
        Scanner s = new Scanner( System.in );

        while( true )
        {
            int x = s.nextInt();
            int y = s.nextInt();

            Pnt curr = new Pnt( x, y );
            System.out.println( solve( curr ));
        }
    }

}
帕斯卡码:

if y * y >= x * x then begin
  p := 4 * y * y - y - x;
  if y < x then
    p := p - 2 * (y - x)
end
else begin
  p := 4 * x * x - y - x;
  if y < x then
    p := p + 2 *(y - x)
end;
如果y*y>=x*x,则开始
p:=4*y*y-y-x;
如果y

描述:左上半对角线(0-4-16-36-64)包含平方层编号(4*层^2)。外部if语句定义图层并在左上半平面的相应行或列中查找位置的(预)结果,内部if语句更正镜像位置的结果

我想加入我的函数,因为它比上一个解决方案更简洁,但比第一个解决方案更复杂。 我的代码不选择索引彼此相邻,而是选择下一个循环的第一个索引始终位于同一轴上的循环/层

像这样:

23 24  9  10 11 +y
22  8  1  2  12
21  7  0  3  13
20  6  5  4  14
19 18 17 16  15 -y
-x           +x
它已设置方向,并使用较小的vec2值作为这些NSEW轴的偏移

func将向量2转换为螺旋索引(vec2):
#层是该位置所在的环层
var层=最大值(abs(vec2.x),abs(vec2.y))
如果层==0:
返回0
#边缘之前的总内部位置
var基本指数=0
变量i=0
而我是:
基本指数+=8*i
i+=1
var电流\u层\u总计=8*i
#每个拐角处的非_轴空间(不是任何nesw轴)
var非轴空间=(当前图层总数-4)/4
#此层上的直接轴空间
变量N=1
变量E=N+非轴空间+1
var S=E+非轴空间+1
var W=S+非轴空间+1
var螺旋指数=基准指数
如果abs(vec2.x)>abs(vec2.y):
如果vec2.x<0:
螺旋线指数+=W
螺旋线指数+=vec2.y
elif vec2.x>0:
螺旋指数+=E
螺旋线指数-=vec2.y
其他:
如果vec2.y<0:
螺旋线指数+=S
elif vec2.y>0:
螺旋指数+=N
#如果x为0,则abs(y)必须等于层
其他:
如果vec2.y<0:
螺旋线指数+=S
螺旋线指数-=vec2.x
elif vec2.y>0:
螺旋指数
变量x=N
x+=vec2.x
#如果x在迭代轴(N)上变成负数,它是从层总数中减去的
如果vec2.x<0:
x=当前\u层\u总计+1+vec2.x
螺旋线指数+=x
其他:
如果vec2.x<0:
螺旋线指数+=W
elif vec2.x>0:
螺旋指数+=E
#如果y为0,则abs(x)必须等于层
回归螺旋指数

也许有一种方法可以缩短这个时间,但我想把它扔掉。

太好了。也很简洁。谢谢