Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spiral Iteration

I need an Algorithm that I will use to scan pixels out from the center. Problem is with different lengths and sizes, it sometimes can't get to the position (See Image below blue part).

Image1

To illustrate the problem more I will show the example output:

Image2

If you compare the pictures you will notice that it goes in a spiral and the outputs match with a regular for loop and obviously the problem that it doesn't print the blue part correctly

Here is the code:

#include<iostream>
#include<string>
#include<math.h>

int arr[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int arrSize = sizeof(arr) / sizeof(arr[0]);
int width = 5;
int height = 3;

void normal2DArray() {
    int index = 0;
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
            index++;
        }
    }
}

int convertToInex(int x, int y) {
    int left = x * y; // elements to the left
    int right = (width - x) * y; // elements to the right
    return left + right + x;
}

void spiralArray() {
    // calculate middle point, which is also the start point
    int x = round((float)width / 2) - 1;
    int y = round((float)height / 2) - 1;

    int direction = 0; // 0=right, 1=up, 2=left, 3=down
    int turnCounter = 1;
    int numSteps = 1;
    int step = 1;
    int index;

    while (true) {

        index = convertToInex(x, y); // defines the index position in arr
        std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";

        switch (direction) {
        case 0: x++; break;
        case 1: y--; break;
        case 2: x--; break;
        case 3: y++; break;
        }
        index = convertToInex(x, y);

        if (step % numSteps == 0) {
            direction = (direction + 1) % 4;
            turnCounter++;
            if (turnCounter % 2 == 0) numSteps++;
        }
        step++;
        if (step > arrSize) break;
    }
}

void main() {
    std::cout << "Output of Normal 2D Array:\n";
    normal2DArray();

    std::cout << "\n"; // better spacing

    std::cout << "Output of Spiral Array:\n";
    spiralArray();
}

I tried to keep the code as simple and small as possible. It should be ready to import and use. And yes I already searched for my answer online but I didn't find anything that covered up the problem here nor had a similar setup like I have(1D arr and combined 2D array WIDTH/HEIGHT) and for sure not in c++.

❗ Also I need a Solution that works with all widths and heights and arr sizes and also works for any side ❗

I hope you can provide me with helpful answers and would be grateful with good and fast algorithm implementations/optimizations

EDIT: Thanks to the replies in this Thread. I decided to go with the solution from @ldog for now even though I'm not completely satisfied with it.

Here are the edited code parts:

    int failcounter = 0;
    while (true) {
    index = convertToInex(x, y); // defines the index position in arr
    if (index < 0 || index > arrSize) failcounter++;
    else std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";

// unchanged code inbetween

if (step > arrSize + failcounter) break;
like image 976
The Developer Fish Avatar asked Jun 22 '26 11:06

The Developer Fish


1 Answers

Based on your comment:

@Beta they don't need to connect. It just has to detect that it's outside the array size (in that case -1) and don't scan them and find the next continue point. So it would continue like this: 5, 1, 6, 11

it seems you don't care that the spiral goes "out-of-bounds". In this case, the trivial answer is, embed the shapes that have no spiral in one that is always guaranteed to have one.

Thus if your input rectangle is N x M, then embed it in a rectangle of size max(M,N) x max(M,N), solve the problem in the latter, and when printing just ignore non-existent numbers in the original problem. Your printed sequence then will always be unique up to how the embedding occurs. The most reasonable embedding would try to center the smaller rectangle as much as possible in the larger rectangle, but this is up to you.

In this case you don't need an algorithm as you can compute everything analytically if you care to do the book-keeping and figure out the formulas involved.

like image 104
ldog Avatar answered Jun 24 '26 00:06

ldog



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!