diff --git a/051_n_queens/n_queens.c b/051_n_queens/n_queens.c index 8f7f9ba..f01dc63 100644 --- a/051_n_queens/n_queens.c +++ b/051_n_queens/n_queens.c @@ -1,17 +1,12 @@ -/* - * Copyright (C) 2015, Leo Ma - */ - #include #include #include -static int N; - static inline int conflict(int *stack, int i, int j) { int k; for (k = 0; k < i; k++) { + /* If occupied or in one line */ if (j == stack[k] || abs(i - k) == abs(j - stack[k])) { return 1; } @@ -20,110 +15,124 @@ static inline int conflict(int *stack, int i, int j) return 0; } -static inline void push(int *stack, int i, int j) +static inline void push(int *stack, int row, int col) { - stack[i] = j; - // printf("push %d %d\n", i, j); + stack[row] = col; } -static inline int pop(int *stack, int i) +static inline int pop(int *stack, int row) { - int j = stack[i]; - stack[i] = -1; - // printf("pop %d %d\n", i, j); - return j; + int col = stack[row]; + stack[row] = -1; + return col; } -static inline int top(int *stack) +static inline int top(int *stack, int n) { - int i; - for (i = N - 1; i >= 0; i--) { - if (stack[i] != -1) { - return i; + int row; + for (row = n - 1; row >= 0; row--) { + if (stack[row] != -1) { + return row; } } return 0; } -void show(int *stack) +static char **solution(int *stack, int n) { - int i, j; - for (i = 0; i < N; i++) { - for (j = 0; j < N; j++) { - if (j == stack[i]) { - printf("Q"); - } else { - printf("."); - } + int row, col; + char **solution = malloc(n * sizeof(char *)); + for (row = 0; row < n; row++) { + char *line = malloc(n + 1); + for (col = 0; col < n; col++) { + line[col] = col == stack[row] ? 'Q' : '.'; } - printf("\n"); + line[n] = '\0'; + solution[row] = line; } + return solution; } -int main(int argc, char **argv) -{ - int i, j, sum = 0; - int *stack; - - if (argc != 2) { - printf("Usage: ./queen 8\n"); - exit(-1); - } - - N = atoi(argv[1]); - if (N <= 0) { - exit(0); +/** + ** Return an array of arrays of size *returnSize. + ** Note: The returned array must be malloced, assume caller calls free(). + **/ +char*** solveNQueens(int n, int *returnSize) { + int row = 0, col = 0, sum = 0; + char ***solutions = malloc(1000 * sizeof(char **)); + + int *stack = malloc(n * sizeof(int)); + for (row = 0; row < n; row++) { + stack[row] = -1; } - stack = malloc(N * sizeof(*stack)); - if (stack == NULL) { - exit(-1); - } - - if (N == 1) { + if (n == 1) { stack[0] = 0; - show(stack); - printf("This is the %dth solution.\n", ++sum); - exit(0); - } - - for (i = 0; i < N; i++) { - stack[i] = -1; + solutions[0] = solution(stack, n); + *returnSize = 1; + return solutions; } - i = j = 0; for (; ;) { - for (; i < N; i++) { - while (j < N) { - if (conflict(stack, i, j)) { - while (j == N - 1) { - /* No space for row[i] so backtracking is needed */ - if (--i < 0) { + for (; row < n; row++) { + while (col < n) { + if (conflict(stack, row, col)) { + while (col == n - 1) { + /* No other positions in this row and therefore backtracking */ + if (--row < 0) { + /* All solution provided */ free(stack); - exit(0); + *returnSize = sum; + return solutions; } - j = pop(stack, i); + col = pop(stack, row); } - j++; + col++; } else { - push(stack, i, j); + push(stack, row, col); break; } } - j = 0; + col = 0; } - i = top(stack); - if (i == N - 1) { - show(stack); - printf("This is the %dth solution.\n", ++sum); + /* Full stack, a new complete solution */ + row = top(stack, n); + if (row == n - 1) { + solutions[sum++] = solution(stack, n); } - j = pop(stack, i); - j++; + /* Move on to find if there are still other solutions */ + col = pop(stack, row); + col++; } assert(0); +} + +int main(int argc, char **argv) +{ + int i, n, row, col, num_of_solution; + + if (argc != 2) { + printf("Usage: ./queen 8\n"); + exit(-1); + } + + n = atoi(argv[1]); + char ***solutions = solveNQueens(n, &num_of_solution); + for (i = 0; i < num_of_solution; i++) { + char **solution = solutions[i]; + for (row = 0; row < n; row++) { + char *line = solution[row]; + for (col = 0; col < n; col++) { + putchar(line[col]); + } + putchar('\n'); + } + printf("The %dth solution.\n", i + 1); + } + return 0; } diff --git a/052_n_queens/Makefile b/052_n_queens/Makefile new file mode 100644 index 0000000..74f9e03 --- /dev/null +++ b/052_n_queens/Makefile @@ -0,0 +1,2 @@ +all: + gcc -O2 -o queen n_queens.c diff --git a/052_n_queens/n_queens.c b/052_n_queens/n_queens.c new file mode 100644 index 0000000..e093550 --- /dev/null +++ b/052_n_queens/n_queens.c @@ -0,0 +1,94 @@ +#include +#include +#include +static inline int conflict(int *stack, int i, int j) +{ + int k; + for (k = 0; k < i; k++) { + /* If occupied or in one line */ + if (j == stack[k] || abs(i - k) == abs(j - stack[k])) { + return 1; + } + } + return 0; +} + +static inline void push(int *stack, int row, int col) +{ + stack[row] = col; +} + +static inline int pop(int *stack, int row) +{ + int col = stack[row]; + stack[row] = -1; + return col; +} + +static inline int top(int *stack, int n) +{ + int row; + for (row = n - 1; row >= 0; row--) { + if (stack[row] != -1) { + return row; + } + } + return 0; +} + +int totalNQueens(int n) { + int row = 0, col = 0, sum = 0, cap = 1; + int *stack = malloc(n * sizeof(int)); + for (row = 0; row < n; row++) { + stack[row] = -1; + } + + if (n == 1) { + return 1; + } + + for (; ;) { + for (; row < n; row++) { + while (col < n) { + if (conflict(stack, row, col)) { + while (col == n - 1) { + /* No other positions in this row and therefore backtracking */ + if (--row < 0) { + /* All solution provided */ + free(stack); + return sum; + } + col = pop(stack, row); + } + col++; + } else { + push(stack, row, col); + break; + } + } + col = 0; + } + + /* Full stack, a new complete solution */ + row = top(stack, n); + if (row == n - 1) { + sum++; + } + + /* Move on to find if there are still other solutions */ + col = pop(stack, row); + col++; + } +} + +int main(int argc, char **argv) +{ + if (argc != 2) { + printf("Usage: ./queen 8\n"); + exit(-1); + } + + int n = atoi(argv[1]); + printf("Total %d solution for %d queens.\n", totalNQueens(n), n); + return 0; +}