3

I have a program and I need a function that takes a coordinate as input and returns an integer corresponding to the position in Ulam's spiral. The simple (but slow) way to do this would be to generate the spiral until you finally find a coordinate that matches the input and then return how many points failed. The more elegant solution would be to write the inverse function of Ulam's spiral. I'm using something this for Ulam's spiral (n is input):

p = floor(sqrt(4 * n + 1));
q = n - floor(p * p / 4);
result = (q - floor((p + 1) / 4)) * i^(p) + floor((p + 2) / 4) * i^(p - 1);

The problem is that I can't seem to figure out what the inverse of Ulam's spiral would be. It seems like the function should have an inverse (it's a bijection, isn't it?), but I have no idea how to solve the inverse of a function with floors and powers of i.

Salech Alhasov
  • 6,780
  • 2
  • 29
  • 47

3 Answers3

3

Is this what you want?

float ulam_spiral(vec2 p)
{
    float x = abs(p.x);
    float y = abs(p.y);
    bool q  = x > y;

    x   = q ? x : y;
    y   = q ? p.x + p.y : p.x - p.y;
    y   = abs(y) + 4. * x * x + 1.;
    x   *= 2.;

    return q 
    ? (p.x > 0. ? y - x - x : y) 
    : (p.y > 0. ? y - x : y + x);   
}


   vec2 inverse_ulam(float u)
   {
    float r = sqrt(u);
    float m = mod(r, 1.);
    float p = mod(r * .5, 1.) > .5 ? 1. : -1.;
    float s = p * 1.5 - m * p * 2.;
    float x = m < .5 ? r * .5 * p : r * s;
    float y = m > .5 ? r * .5 * p : r * p - r * s;

    return vec2(x, y);
}
2

Note that the squares are on diagonals. Can you write two formulas for where $k^2$ is? One for even $k$, one for odd. You can find $k$ by taking $\sqrt n$ and rounding down. Then we can figure the offset from $k^2$ to $n$.

If $1$ is at $(0,0)$, odd $k^2$ is at $(\frac 12(k-1),-\frac 12(k-1))$. Even $k^2$ is at $(1-\frac k2,\frac k2-1)$ The sides of the square are $k+1$ long and you need to count $n-k^2$ spaces along the way. The next side of the square is side is $k+1$ long, then we turn a corner and go $k$ more (but we will never go all the way because $k$ would increase). So our algorithm is Let $k=\lfloor \sqrt n \rfloor, m=n-k^2$
If $k$ is even, the location of $k^2$ is $(1-\frac k2,\frac k2-1)$
If $m \le k+1,$ the location of $n$ is the location of $k^2 + (-1,-(m-1))$
If $m \gt k+1,$ the location of $k^2+k+1$ is $(1-\frac k2,1-\frac k2)$
Let $m=n-(k^2+k+1)$ the location of $n$ is the location of $k^2+k+1 + (m,0)$

If $k$ is odd, the location of $k^2$ is $(\frac 12(k-1),-\frac 12(k-1))$
If $m \le k+1,$ the location of $n$ is the location of $k^2 + (1,m-1)$
If $m \gt k+1,$ the location of $k^2+k+1$ is $(-1+\frac k2,-1+\frac k2)$
Let $m=n-(k^2+k+1)$ the location of $n$ is the location of $k^2+k+1 + (-m,0)$

I hope you can see the pattern. You start from a corner and count up as far as needed. It would be good to check this.

Ross Millikan
  • 374,822
  • There are a few issues with the formulas: (1) The approach does not work if "n" is a square and thus "m" is "0". These cases must be handled separately. If "m = 0" then the location of "n" is equal to the location of "k2". (2) When "k" is even the location of "k^2" is "(1 - k/2, k/2)" and not "(1 - k/2, k/2 - 1)". (3) When "k" is even the location of "k^2 + k + 1" is "(-k/2, -k/2)" and not "(1 - k/2, 1 - k/2)". (4) When "k" is odd the location of "k^2 + k + 1" is "((k+1) / 2, (k+1) / 2)" and not "(−1 + k/2, −1 + k/2)" – fluidsonic May 27 '20 at 16:35
0

I don't understand what all these machinations are about. I assume that in your code that $n$ goes from 1 to whatever, and then you plot the cumulative result, e.g.,

z=[];

for n=1:1000

% your code

z=[z;result];

end

Then, you can plot 1./z, and that's the inverse.

Cye Waldman
  • 7,524