Skip to content

Instantly share code, notes, and snippets.

@andrew-d
Created September 17, 2013 05:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrew-d/6590357 to your computer and use it in GitHub Desktop.
Save andrew-d/6590357 to your computer and use it in GitHub Desktop.
Spiral array generator
#include <stdio.h>
#include <stdlib.h>
// Define me for interactivity!
//#define DEBUG
void print_matrix(int* matrix, int x, int y) {
int i, j;
for( i = 0; i < y; i++ ) {
for( j = 0; j < x; j++ ) {
if( matrix[i*x + j] == 0 ) {
printf(" ");
} else {
printf("%2d ", matrix[i*x + j]);
}
}
printf("\n");
}
}
int* spiral_inner(int* ret, int* mem, int size, int n, int start, int remain) {
int* ptr = mem;
int offset[] = {1, +size, -1, -size};
// End case: no remaining numbers.
if( 0 == remain ) {
return;
}
// Always fill current cell.
*ptr++ = start;
// General idea:
// X - n-1 -> Y
// ^ |
// | n-1
// n-2 |
// | v
// Q <- n-1 - Z
int edge = 0;
int currDirectionCtr = 1;
int i, currLimit = n - 1;
for( i = start + 1; i < remain; i++, currDirectionCtr++ ) {
#ifdef DEBUG
printf("Writing to cell %ld x %ld\n",
((ptr - ret) % size) + 1,
((ptr - ret) / size) + 1);
#endif
// Write this current
*ptr = i;
// Check if we're too far.
#ifdef DEBUG
printf("Have moved %d / %d steps in current direction\n",
currDirectionCtr, currLimit);
#endif
if( currDirectionCtr == currLimit ) {
edge++;
if( edge == 3 ) {
currLimit -= 1;
} else if( edge > 3 ) {
break;
}
currDirectionCtr = 0;
}
// Move in the right direction.
#ifdef DEBUG
printf("edge = %d\n", edge); fflush(stdout);
printf("Moving ptr by: %d\n", offset[edge]); fflush(stdout);
#endif
ptr = ptr + offset[edge];
#ifdef DEBUG
print_matrix(ret, size, size);
printf("Curr pos: %ld x %ld\n",
((ptr - ret) % size) + 1,
((ptr - ret) / size) + 1);
getchar();
printf("--------------------\n");
#endif
}
if( i < remain ) {
#ifdef DEBUG
printf("====================\n");
#endif
return spiral_inner(ret, ptr + 1, size, n - 2, i + 1, remain);
}
}
int* spiral(int n, int limit) {
int* ret = calloc(n * n, sizeof(int));
spiral_inner(ret, ret, n, n, 1, limit);
// Our condition above will cause even numbers to not write the
// last number. We fill in the last number if the limit allows.
if( (n % 2 == 0) && (limit == (n * n)) ) {
// Explanation:
// (n / 2) = middle column
// (n / 2) * n = middle row
// -1 = back one column, since it's even
*(ret + (n/2) + (n/2)*n - 1) = limit;
}
return ret;
}
int main(void) {
int n;
int* ret;
printf("Spiral\n");
printf("Enter n: ");
scanf("%d", &n);
getchar();
printf("Generating spiral of size %dx%d...", n, n);
fflush(stdout);
ret = spiral(n, n * n);
printf(" done!\n");
printf("\nOutput:\n");
print_matrix(ret, n, n);
free(ret);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment