Welcome to collectivesolver - Programming & Software Q&A with code examples. A website with trusted programming answers. All programs are tested and work.

Contact: aviboots(AT)netvision.net.il

Semrush - keyword research tool

Turn ChatGPT, Claude, Gemini, And CoPilot Into Your Personal Assistant, Business Coach, Content Creator, And More

AFFILIATE MARKETING Your all-in-one performance engine Manage affiliates, creators, and customer referrals in one unified platform—turning every partnership into measurable growth
Secure & Reliable Web Hosting, Free Domain, Free SSL, 1-Click WordPress Install, Expert 24/7 Support

Boost your online presence with premium web hosting and servers

Disclosure: My content contains affiliate links.

42,596 questions

55,330 answers

573 users

How to generate a random 3×3 magic square in C

1 Answer

0 votes
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 3
#define CELLS (N * N)
#define MAX_MAGIC_SQUARES 8  /* exact count for digits 1-9 */

/* A square is stored as 9 ints in row-major order: index = row*3 + col */
typedef struct {
    int cell[CELLS];
} Square;

/* Advances 'arr' (length n) to the next lexicographic permutation in place.
 * Returns 1 if a next permutation exists, 0 if 'arr' was already the last
 * (fully descending) permutation. This is the standard constant-amortized
 * algorithm: find the rightmost ascent, find the smallest element to its
 * right that is still larger, swap, then reverse the suffix. */
int next_permutation(int *arr, int n) {
    int i = n - 2;
    while (i >= 0 && arr[i] >= arr[i + 1]) {
        --i;
    }
    if (i < 0) {
        return 0; /* already the last permutation */
    }

    int j = n - 1;
    while (arr[j] <= arr[i]) {
        --j;
    }

    int tmp = arr[i]; arr[i] = arr[j]; arr[j] = tmp;

    for (int lo = i + 1, hi = n - 1; lo < hi; ++lo, --hi) {
        tmp = arr[lo]; arr[lo] = arr[hi]; arr[hi] = tmp;
    }
    return 1;
}

/* Checks whether 'sq' is magic: every row, every column, and both
 * diagonals must sum to the same value. Returns 1 and writes that common
 * sum into *magic_sum if the square qualifies; returns 0 otherwise. */
int is_magic(const Square *sq, int *magic_sum) {
    int row_sum[N] = {0}, col_sum[N] = {0};
    int main_diag = 0, anti_diag = 0;

    for (int r = 0; r < N; ++r) {
        for (int c = 0; c < N; ++c) {
            int v = sq->cell[r * N + c];
            row_sum[r] += v;
            col_sum[c] += v;
            if (r == c)         main_diag += v; /* top-left to bottom-right */
            if (r == N - 1 - c) anti_diag += v; /* top-right to bottom-left */
        }
    }

    *magic_sum = row_sum[0];
    for (int r = 0; r < N; ++r) if (row_sum[r] != *magic_sum) return 0;
    for (int c = 0; c < N; ++c) if (col_sum[c] != *magic_sum) return 0;
    return (main_diag == *magic_sum) && (anti_diag == *magic_sum);
}

/* Enumerates all 9! = 362,880 permutations of {1,...,9} via
 * next_permutation (lexicographic order, no duplicates, no extra memory),
 * and collects every arrangement that forms a magic square into 'out'.
 * Returns the number of magic squares found. This exhaustive pass is
 * cheap: 362,880 iterations of O(1) work, well under a second at runtime. */
int collect_all_magic_squares(Square out[MAX_MAGIC_SQUARES]) {
    int current[CELLS];
    for (int i = 0; i < CELLS; ++i) {
        current[i] = i + 1; /* fill with 1..9 */
    }

    int count = 0;
    do {
        Square candidate;
        for (int i = 0; i < CELLS; ++i) {
            candidate.cell[i] = current[i];
        }
        int sum;
        if (is_magic(&candidate, &sum)) {
            if (count < MAX_MAGIC_SQUARES) {
                out[count++] = candidate;
            }
        }
    } while (next_permutation(current, CELLS));

    return count;
}

/* Prints a square in a readable grid layout, plus its magic sum. */
void print_square(const Square *sq) {
    for (int r = 0; r < N; ++r) {
        for (int c = 0; c < N; ++c) {
            printf("%d%c", sq->cell[r * N + c], (c < N - 1) ? ' ' : '\n');
        }
    }
    int sum;
    is_magic(sq, &sum);
    printf("Magic sum per row/column/diagonal: %d\n", sum);
}

int main(void) {
    /* Step 1: build the full list of valid 3x3 magic squares (digits 1-9)
     * once. There are exactly 8, so a fixed-size array is sufficient and
     * avoids any dynamic memory management. */
    Square all_magic_squares[MAX_MAGIC_SQUARES];
    int count = collect_all_magic_squares(all_magic_squares);

    if (count == 0) {
        fprintf(stderr, "No magic squares found (unexpected).\n");
        return 1;
    }

    /* Step 2: pick one uniformly at random. Seed the standard library's
     * pseudo-random generator once from the current time, then use
     * rand() with the classic scaling trick to get an unbiased index
     * in range [0, count). */
    srand((unsigned int)time(NULL));
    int index = rand() % count;
    const Square *chosen = &all_magic_squares[index];

    printf("Found %d valid 3x3 magic squares (digits 1-9).\n", count);
    printf("Randomly selected one:\n\n");
    print_square(chosen);

    return 0;
}


/*
run:

Found 8 valid 3x3 magic squares (digits 1-9).
Randomly selected one:

4 9 2
3 5 7
8 1 6
Magic sum per row/column/diagonal: 15

*/

 



answered 1 day ago by avibootz

Related questions

1 answer 273 views
...