Start 0,0 centered spiral from an arbitrary point

124 views Asked by At

I am trying to make a spiral centred in (0,0) that you can start form any arbitry point inside it.

In other words: the spiral should have the shape of one that started at 0,0 but starting from an arbitrary point (as if you removed previous positions)

I made the following code but it only works when both initX and initY are 0:

void printSpiralCoords(int32_t initX, int32_t initY, uint32_t steps) {

    int8_t dx = 0;
    int8_t dy = 0;

    uint32_t stepsDone = 0;
    uint32_t length = 0;

    uint32_t absX = abs(initX);
    uint32_t absY = abs(initY);


    if (absX > absY) {
        if (initX >= 0) {
            dy = 1;
        }
        else {
            dy = -1;
        }
        stepsDone = absY;
        length = absX;
    }
    else {
        if (initY >= 0) {
            dx = 1;
        }
        else {
            dx = -1;
        }
        stepsDone = absX;
        length = absY;
    }

    if (length == 0) {
        length = 1;
    }


    for (uint32_t i = 0; i < steps; i++) {

        printf("x: %d, z: %d\n", initX, initY);

        initX += dx;
        initY += dy;

        stepsDone++;
        if (stepsDone >= length) {
            stepsDone = 0;
            if (dx == 0) {
                dx = -dy;
                dy = 0;
                length++;
            }
            else {
                dy = dx;
                dx = 0;
            }
        }
    }
}

Rules:

  • Spiral should always turn left
  • You cannot build from 0,0 every time and "ignore" previous blocks
  • Sice steps variable can be up to 2^32-1 cannot use lookup table

Here is an example on how it should work: Starting at (0,0):

Starting at (0,1):

2

There are 2 answers

2
a_name On

At init you can use some statement to know where you are in the spiral :

if (x > 0 && x == y) // your top right

else if (x <= 0 && x == y) // your bottom left or 0, 0

else if (x < 0 && x * -1 == y) // your top left

else if (x > 0 && (x - 1) * -1 == y) // your bottom right

else if (x < 0 && ...) // left side (figure you that one by yourself)

else if (x > 0 && ...) // right side (figure you that one by yourself)

else if (y < 0 && ...) // bottom side (figure you that one by yourself)

else if (y > 0 && ...) // top side (figure you that one by yourself)

After you can use that knowledge to step in the spiral.

7
Eric Postpischil On

The problem may be stated as: Given a point (x, y) in the sequence, determine the next point in the sequence, and the points after that.

The sequence consists of intervals of moving right, then moving up, then moving left, then moving down, and repeating. The turns largely occur on the diagonal lines y = x and y = −x. Therefore, we can determine which way to move based on comparison with those lines, with some care about exactly where the transitions occur:

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>


typedef struct { int32_t x, y; } Point;


static Point Next(Point a)
{
    //  If we are on or left of y = x and right of y = -x, move left.
    if (a.x <= a.y && -a.x < a.y)
        return (Point) { a.x-1, a.y };

    //  If we are on or below y = -x and above y = x, move down.
    if (a.y <= -a.x && a.x < a.y)
        return (Point) { a.x, a.y-1 };

    //  If we are on or right of y = x and on or left of y = -x, move right.
    if (a.y <= a.x && a.y <= -a.x)
        return (Point) { a.x+1, a.y };

    //  Otherwise, move up.
    else
        return (Point) { a.x, a.y+1 };
}


int main(void)
{
    Point a = { 0, 0 };

    printf("(%" PRId32 ", %" PRId32 ")\n", a.x, a.y);
    for (int i = 0; i < 10; ++i)
    {
        a = Next(a);
        printf("(%" PRId32 ", %" PRId32 ")\n", a.x, a.y);
    }
}

Then reorganizing the comparisons can give us:

static Point Next(Point a)
{
    //  Are we above-right of y = -x?
    if (-a.x < a.y)

        /*  If we are also on or below-left of y = x, move left.
            Otherwise, move up.
        */
        return a.x <= a.y ? (Point) { a.x-1, a.y } : (Point) { a.x, a.y+1};

    //  Otherwise, we are on or below-left of y = -x.
    else

        /*  If we are also  above-left of y = x, move down.
            Otherwise, move right.
        */
        return a.x < a.y ? (Point) { a.x, a.y-1 } : (Point) { a.x+1, a.y };
}