loading...

Daily Challenge #98 - Make a Spiral

thepracticaldev profile image dev.to staff ・1 min read

Your task is to create an NxN spiral with a given size.
For example, a spiral with size 5 should look like this:

00000
....0
000.0
0...0
00000

and with the size 10:

0000000000
.........0
00000000.0
0......0.0
0.0000.0.0
0.0..0.0.0
0.0....0.0
0.000000.0
0........0
0000000000

Return value should contain array of arrays, of 0 and 1, for example for given size 5 result should be:

[[1,1,1,1,1],[0,0,0,0,1],[1,1,1,0,1],[1,0,0,0,1],[1,1,1,1,1]]

Because of the edge-cases for tiny spirals, the size will be at least 5.

General rule-of-a-thumb is, that the snake made with '1' cannot touch to itself.


This challenge comes from Bugari on CodeWars, who has licensed redistribution of this challenge under the 2-Clause BSD License!

Want to propose a challenge idea for a future post? Email yo+challenge@dev.to with your suggestions!

Discussion

pic
Editor guide
Collapse
erezwanderman profile image
erezwanderman

Javascript:

const spiral = n => {
  return Array(n)
    .fill(Array(n).fill())
    .map((x, r) =>
      x.map((y, c) => {
        return +(
          // top
          (r < n / 2 && r % 2 === 0 && c >= r - 2 && c <= n - r - 1) ||
          // right
          ((n - c) % 2 === 1 && r > n - c - 1 && r <= c) ||
          // bottom
          ((n - r) % 2 === 1 && c > n - r - 1 && c < r) ||
          // left
          (c % 2 === 0 && r > c + 1 && r < n - c)
        );
      })
    );
};

See it in action: codesandbox.io/s/hopeful-nash-wvvc...

Collapse
erezwanderman profile image
erezwanderman

Now I'm working on generalizing it to non square matrix

Collapse
erezwanderman profile image
erezwanderman
const spiral = (rowNum, colNum) => {
  return Array(rowNum)
    .fill(Array(colNum).fill())
    .map((x, r) =>
      x.map((_, c) => {
        return +(
          // top
          (r < rowNum / 2 && r % 2 === 0 && r - 2 <= c && c <= colNum - r - 1) ||
          // right
          (c > (colNum - 2) / 2 && (colNum - c) % 2 === 1 && colNum - c - 2 < r && r <= rowNum - (colNum - c)) ||
          // bottom
          (r > rowNum / 2 && (rowNum - r) % 2 === 1 && rowNum - r - 2 < c && c < colNum - (rowNum - r)) ||
          // left
          (c < (colNum - 2) / 2 && c % 2 === 0 && r > c + 1 && r < rowNum - c)
        );
      })
    );
};
Collapse
edreeseg profile image
Ed Reeseg

Definitely not as efficient as iterating through each index once and deciding on a 1 or a 0 arithmetically, but I wanted to try solving this one in a different way to see how it worked out. I'd probably go back and refactor this a bit, given the choice, but it seems to work well enough.

If we had a way of initializing the array values at 0, this method could actually be more efficient, as it wouldn't necessitate visiting every single index, just those touched by the spiral.

C

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, char **argv)
{
    int size = atoi(argv[1]);
    if (argc != 2 || size < 5)
    {
        printf("Usage: ./make-a-spiral.c int\n");
        return 1;
    }
    int result[size][size];
    int x = 0,
        y = 0,
        dir = 1,
        horizontal = 1,
        boundary_x = 0,
        boundary_y = 0,
        turns = 0;
    // Iterate through our result array and set the default to 0,
    // as otherwise we will end up with garbage values polluting the result.
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            result[i][j] = 0;
        }
    }
    // Change our x and y location as is appropriate, and check when we 
    // need to turn.
    while (turns < size)
    {
        result[y][x] = 1;
        if (y == 0 + boundary_y && !horizontal && dir == -1)
        {
            horizontal = 1;
            dir *= -1;
            turns++;
        }
        else if (y == size - boundary_y - 1 && !horizontal && dir == 1)
        {
            horizontal = 1;
            boundary_y += 2;
            dir *= -1;
            turns++;
        }
        else if (x == size - boundary_x - 1 && horizontal && dir == 1)
        {
            horizontal = 0;
            turns++;
        }
        else if (y != 0 && x == 0 + boundary_x && horizontal && dir == -1)
        {
            horizontal = 0;
            boundary_x += 2;
            turns++;
        }
        // Handle movement
        if (horizontal)
        {
            x += dir;
        }
        else 
        {
            y += dir;
        }
    }
    // Iterate through once more to print the resulting spiral.
    for (int i = 0; i < size; i++)
    {
        for (int j = 0; j < size; j++)
        {
            printf("%c", result[i][j] ? '0' : '.');
        }
        printf("\n");
    }
    return 0;
}
Collapse
aschwin profile image
Aschwin Wesselius

Sprial or spiral?

The title says sprial, the article says spiral.

Collapse
michaeltharrington profile image