Reputation: 71
#include <stdio.h>
int main()
{
int arr[9][9];
int i = 0, x = 10;
for (int i = 0, j = 0; j <= 8; j++) {
x++;
arr[i][j] = x;
}
for (int j = 8, i = 1; i <= 8; i++) {
x++;
arr[i][j] = x;
}
for (int i = 8, j = 7; j >= 0; j--) {
x++;
arr[i][j] = x;
}
for (int j = 0, i = 7; i >= 1; i--) {
x++;
arr[i][j] = x;
}
for (int i = 1, j = 1; j <= 7; j++) {
x++;
arr[i][j] = x;
}
for (int j = 7, i = 2; i <= 7; i++) {
x++;
arr[i][j] = x;
}
for (int i = 7, j = 6; j >= 1; j--) {
x++;
arr[i][j] = x;
}
for (int j = 1, i = 6; i >= 2; i--) {
x++;
arr[i][j] = x;
}
...
arr[4][4] = x + 1;
for (int i = 0; i <= 8; i++) {
for (int j = 0; j <= 8; j++)
printf("%d ", arr[i][j]);
printf("\n");
}
getch();
}
so I have this program, and I know you can loop it but how ? been sitting for an hour thinking and nothing came to my mind. By the way, the task is to append a matrix like on picture. Does anyone know to do it ? Maybe use some complex for loop
Upvotes: 1
Views: 212
Reputation: 1922
It's possible to deterministically compute any one entry in the array A_{i,j}
as a function only given the array size N
, and i
, j
, in O(1)
, on-line, without any state, noticing the radius is a geometric progression. The space requirement is O(1)
since one doesn't actually need the array to store the values; we can scan the array sequentially. However, like ray-tracing, it probably is slower, (up to a constant, it's still O(N^2)
.)
#include <stdio.h>
/* N: The size of the (simulated) array. */
#define N (16)
/* i, j: The array indices, as if, a[i][j]. */
static int a(const int i, const int j) {
/* (x,y) translation of (i,-j) to the centre, scaled up 2x for int math. */
const int x = 2 * i + 1 - N, y = -2 * j - 1 + N;
/* Geometric series and an offset +fiddling to get the directionality. */
return N*N - ((x < -y) ?
(-x > -y) ? (x+1)*(x+1) - (y+x)/2 - 1: y*y + (x+y)/2 :
(x > y) ? x*x + (x+y)/2 : (y+1)*y + (-x+y)/2);
}
int main(void) {
int i, j;
for(j = 0; j < N; j++) {
for(i = 0; i < N; i++) {
printf("%3d ", a(i, j));
}
printf("\n");
}
return 0;
}
Upvotes: 0
Reputation: 140960
My solution. Using an "object" struct strangeite_s
(from strange ite-rator). It allows ease reusing on different arrays and probably could be even rescaled to support n-dimensional arrays.
The strangeite
is initialized using _init
function with specified dimensions sizes of an 2d array. Each time _loop
is evaluated, the x
and y
positions are updated and the condition for loop end is checked (and returned). The _inc
function should be called on each increment of the iterator.
#include <stdio.h>
#include <limits.h>
#include <stddef.h>
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <stdbool.h>
struct strangeite_s {
size_t steplen[2];
size_t idx[2];
size_t cursteplen;
int direction;
};
void strangeite_init(struct strangeite_s *t, size_t max_x, size_t max_y)
{
assert(t != NULL);
t->steplen[0] = max_y;
t->steplen[1] = max_x;
memset(t->idx, 0, sizeof(t->idx));
t->direction = 0;
t->cursteplen = t->steplen[0];
}
bool strangeite_loop(const struct strangeite_s *t, size_t *x, size_t *y)
{
if (x) *x = t->idx[0];
if (y) *y = t->idx[1];
for (size_t i = 0; i < sizeof(t->steplen)/sizeof(t->steplen[0]); ++i) {
if (t->steplen[i] == 0) {
return false;
}
}
return true;
}
void strangeite_inc(struct strangeite_s *t)
{
if (t->cursteplen != 1) {
--t->cursteplen;
} else {
t->direction = ++t->direction % (2 * 2);
t->cursteplen = --t->steplen[t->direction % 2];
}
const size_t idx_to_change = t->direction % 2;
t->idx[idx_to_change] = t->idx[idx_to_change] + ( t->direction < 2 ? +1 : -1 );
}
int main()
{
int var[5][5];
struct strangeite_s i;
strangeite_init(&i, 5, 5);
int idx = 0;
for (size_t x, y; strangeite_loop(&i, &x, &y); strangeite_inc(&i)) {
var[y][x] = ++idx;
}
for (size_t i = 0; i < 5; ++i) {
for (size_t j = 0; j < 5; ++j) {
printf("%d ", var[i][j]);
}
printf("\n");
}
return 0;
}
Produces the following output:
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Live version at onlinegdb.
Upvotes: 0
Reputation: 6875
Here is the "straight forward" option with for
loops:
#include <stdio.h>
#define N 5
int main(void) {
int i,j,dim;
int matrix[N][N];
// init and print the matrix
for (i=0; i < N; i++)
{
for (j=0; j< N; j++)
{
matrix[i][j] = i*N + j;
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
printf("\n");
// perform spiral print
for (dim = 0; dim < (N+1)/2; dim++)
{
// set initial i and go till the "last column"
i = dim;
for (j = dim; j < N - dim; j++)
{
printf("%2d ", matrix[i][j]);
}
printf("\n");
// bring back i and j to the proper coordinate
// and move down to the "last row"
j--;i++;
for (; i < N - dim; i++)
{
printf("%2d ", matrix[i][j]);
}
printf("\n");
// bring back i and j to the proper coordinate
// and move back to the "first column"
i--;j--;
for (; j >= dim; j--)
{
printf("%2d ", matrix[i][j]);
}
printf("\n");
// bring back i and j to the proper coordinate
// and move up to the "first row"
j++;i--;
for (; i > dim; i--)
{
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
The output, as can be seen here is
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
0 1 2 3 4
9 14 19 24
23 22 21 20
15 10 5
6 7 8
13 18
17 16
11
12
==========================================================================
Looks like I misunderstood the question but the step from "printing" clockwise to "setting" clockwise is really small. Here is the setting flow:
#include <stdio.h>
#define N 5
int main(void) {
int i,j,dim, val = 1;
int matrix[N][N];
// perform spiral print
for (dim = 0; dim < (N+1)/2; dim++)
{
// set initial i and go till the "last column"
i = dim;
for (j = dim; j < N - dim; j++)
{
matrix[i][j] = val++;
}
// bring back i and j to the proper coordinate
// and move down to the "last row"
j--;i++;
for (; i < N - dim; i++)
{
matrix[i][j] = val++;
}
// bring back i and j to the proper coordinate
// and move back to the "first column"
i--;j--;
for (; j >= dim; j--)
{
matrix[i][j] = val++;
}
// bring back i and j to the proper coordinate
// and move up to the "first row"
j++;i--;
for (; i > dim; i--)
{
matrix[i][j] = val++;
}
}
// print the matrix
for (i=0; i < N; i++)
{
for (j=0; j< N; j++)
{
printf("%2d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
The output as shown here is
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
Upvotes: 1
Reputation: 13269
Here's one way to do it:
int arr[9][9] = {0};
int x = 0, i = 0, j = 0, vi = 0, vj = 1;
do {
++x;
arr[i][j] = x;
{
int ii = i+vi;
int jj = j+vj;
if (ii < 0 || ii >= 9 || jj < 0 || jj >= 9 || arr[ii][jj] != 0) {
if (vi != 0) {
vj = -vi;
vi = 0;
} else {
vi = vj;
vj = 0;
}
}
}
i = i+vi;
j = j+vj;
} while (arr[i][j] == 0);
Here's another way:
int arr[9][9] = {0};
int x = 0, i = 0, j = 0, vi = 0, vj = 1, lk = 8;
while (lk > 0) {
for (int k = 0; k < lk; ++k) {
++x;
arr[i][j] = x;
i += vi;
j += vj;
}
vi = vj;
vj = 0;
for (int k = 0; k < lk; ++k) {
++x;
arr[i][j] = x;
i += vi;
j += vj;
}
vj = -vi;
vi = 0;
if (vj > 0) {
++i;
++j;
lk -= 2;
}
}
arr[9/2][9/2] = x+1; // Only if odd dimensions
And here is yet another:
int arr[9][9] = {0};
int i = 0, lk = 8, x = 1;
while (lk > 0) {
for (int k = 0; k < lk; ++k) {
arr[i][i+k] = x + k;
arr[i+k][lk+i] = x + lk + k;
arr[lk+i][lk+i-k] = x + 2*lk + k;
arr[lk+i-k][i] = x + 3*lk + k;
}
x += 4*lk;
lk -= 2;
++i;
}
arr[9/2][9/2] = x; // Only if odd dimensions
Upvotes: 1