#include <stdio.h>
#include <math.h>
int n=4;
int GetQueenSettings(int board[4][4],int currentRow,int n)
{
//decide when the recursion stops
if(currentRow==n)
return 1; //successful setting
//otherwise we set column by column in this row and continue
int TotalSettingCount=0;
for(int i=0;i<n;i++)
{
//make sure it can be set (it is unset at that moment)
if(board[currentRow][i]==0)
{
board[currentRow][i]==1+currentRow;
//use row related info for settings
//now set invalid positions for remaining rows
setInvalid(board,currentRow,n,i);
//recover after this before trying the next
TotalSettingCount += GetQueenSettings(board,currentRow+1,n);
board[currentRow][i]=0;
RecoverBoard(board,currentRow,n);
}
}
return TotalSettingCount;
}
void setInvalid(int board[4][4],int currentRow,int n,int i)
{
//vertical and diagonal elements
for(int row=currentRow+1;row<n;row++) //start from the next line
{
//firstly make sure board can be set
if(board[row][i]==0)//vertical position
board[row][i]=-(1+currentRow);
//now check diagonal
int rowGap=row-currentRow;
if(i-rowGap>=0 && board[row][i-rowGap]==0)
{
//left bottom diagonal position
board[row][i-rowGap]=-(1+currentRow);
}
if(i+rowGap<n && board[row][i+rowGap]==0)
{
//bottom right diagonal position
board[row][i+rowGap]=-(1+currentRow);
}
}
}
void RecoverBoard(int board[4][4],int currentRow,int n)
{
//recover is to check all remaining rows if index is higher than current row(setters)
//OR less than -currentRow(invalids)!
for(int row=currentRow+1;row<n;row++)
{
for(int col=0;col<n;col++)
{
if(board[row][col]>currentRow || board[row][col]< -currentRow)
board[row][col]=0;
}
}
}
int main()
{
int board[n][n];
printf("Number of settings:-> %d",GetQueenSettings(board,0,n));
return 0;
}
There are N queeens placed on a NxN chessboard without interfering with each other. when i run this code i get the answer as zero instead of 2 . also i cant figure out a way of passing array board to functions with variable size(size will be given by user).What am i doing wrong?!
You should initialize your board. As is, you start with a board full of garbage values. You are using a variable-length array as board. Such arrays cannot be initialized, so you have to set the board to all zero with a loop or with memset from <string.h>:
int board[n][n];
memset(board, 0, sizeof(board));
You can pass variable-length arrays to functions when the dimensions are passed in as earlier arguments, for example:
int GetQueenSettings(int n, int board[n][n], int currentRow) { ... }
Also fix the =/== switch in setInvalid:
if (board[row][i] == 0)
board[row][i] = -(1 + currentRow);
Finally make sure that all functions have proper prototypes when they are called.
A loooooooong time ago I developed an algorithm like the one you have, maybe it can help you.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long Solutions;
void AllocBoard(int *** Board, int Queens)
{
int i;
*Board = (int **)malloc(sizeof(int *) * Queens);
for(i = 0; i < Queens; i++)
{
(*Board)[i] = (int *)malloc(sizeof(int) * Queens);
memset((*Board)[i], 0, sizeof(int) * Queens);
}
}
void DeallocBoard(int *** Board, int Queens)
{
int i;
for(i = 0; i < Queens; i++)
free((*Board)[i]);
free(*Board);
}
void SavePosition(int *** Board, int Queens, int Col, int Row, int Inc)
{
int i, j;
for(i = 0; i < Queens; i++)
{
if((*Board)[Col][i] >= 0) (*Board)[Col][i] += Inc;
if((*Board)[i][Row] >= 0) (*Board)[i][Row] += Inc;
}
for(i = Col, j = Row; j < Queens && i < Queens; i++, j++)
if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
for(i = Col, j = Row; j >= 0 && i >= Col; i--, j--)
if((*Board)[i][j] >= 0) (*Board)[Col][j] += Inc;
for(i = Col, j = Row; j >= 0 && i < Queens; i++, j--)
if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
for(i = Col, j = Row; j < Queens && i >= Col; i--, j++)
if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
}
void FindSolutions(int *** Board, int Queens, int Col)
{
int i, j;
for(i = 0; i < Queens; i++)
{
if((*Board)[Col][i] != 0) continue;
(*Board)[Col][i] = -1;
if(Col + 1 == Queens)
Solutions++;
else
{
SavePosition(Board, Queens, Col, i, 1);
FindSolutions(Board, Queens, Col + 1);
SavePosition(Board, Queens, Col, i, -1);
}
(*Board)[Col][i] = 0;
}
}
void main(int argc, char **argv)
{
int Queens, ** Board = NULL;
clock_t Start, End;
clrscr();
if(argc < 2)
Queens = 8;
else
Queens = atoi(argv[1]);
Solutions = 0;
Start = clock();
AllocBoard(&Board, Queens);
FindSolutions(&Board, Queens, 0);
DeallocBoard(&Board, Queens);
End = clock();
printf("Solutions %ld\n", Solutions);
printf("Estimated time: %f", (End - Start) / CLK_TCK);
getch();
}
Hope this helps
Asking "why it doesn't work" about short and simple programs is not very well. Try debug it yourself with any debugger or simply using printing in important places/on each step. Actually, C has no arrays, instead it has pointers. You can work with them very alike, that is why all you need is to change int board[4][4] to int **board and add one argument: int N(count of cells) and that's all. All your other code shouldn't be changed.
Related
The problem is to create an array of player ranks based on 2 other arrays: leaderboard and player scores. More explanations of the problem here: https://www.hackerrank.com/challenges/climbing-the-leaderboard/problem.
The code below is a spaghetti but it's working fine. But, for large size of ranked array(200000 elements for example), it times out. I'm not asking for code to copy/paste. I just wanna know if there is a way to optimize this code.
int* climbingLeaderboard(int ranked_count, int* ranked, int player_count, int* player, int* result_count) {
*result_count=player_count;
// remove duplicates
int removed=0;
for(int i=0, j=1; i<ranked_count-removed; i++, j++){
if(ranked[i]==ranked[j]){
for(int k=j; k<ranked_count-removed; k++)
ranked[k]=ranked[k+1];
removed++;
}
}
int newsize=ranked_count-removed;
// create an array to store ranks then fill it
int* positions=malloc(newsize*sizeof(int));
positions[0]=1;
for(int i=0, j=1; j<newsize; i++, j++){
positions[j]=(ranked[j]<ranked[i])? (positions[i]+1) : positions[i];
}
// create and fill the results array using binary search
int* res = malloc(player_count*sizeof(int));
int start=0, end=newsize-1, middle=(start+end)/2;
int j, k=newsize-1;
for(int i=0; i<player_count; i++){
if(i>0&&player[i]==player[i-1]){
*(res+i)=(*(res+(i-1)));
continue;
}
if(player[i]>=ranked[middle]){
*(res+i)=positions[middle];
j=middle-1;
while(j>=0){
if(player[i]>=ranked[j])
*(res+i)=positions[j];
else if(j==k)
*(res+i)=positions[j]+1;
else break;
--j;
}
start=0; end=middle-1;
}
else{
*(res+i)=positions[newsize-1]+1;
j=newsize-1;
while(j>=middle){
if(player[i]>=ranked[j])
*(res+i)=positions[j];
else if(j==k)
*(res+i)=positions[j]+1;
else break;
--j;
}
start=middle+1; end=newsize-1;
}
middle=(start+end)/2;
}
free(positions);
return res;
}
The initial loop to remove duplicates has a potential quadratic time complexity. You can achieve linear complexity using the 2 finger approach:
int removed = 0;
for (int i = 1, j = 1; j < ranked_count; j++) {
if (ranked[i - 1] != ranked[j])
ranked[i++] = ranked[j];
else
removed++;
}
More generally, the argument arrays should not be changed in spite of the sloppy prototype given:
int *climbingLeaderboard(int ranked_count, int *ranked,
int player_count, int *player,
int *result_count);
Here are simple steps I would recommend to solve this problem:
allocate and initialize a ranking array with the ranking for each of the scores in the ranked array. Be careful to allocate ranked_count + 1 elements.
allocate a result array res of length player_count, set the result_count to player_count.
starting with pos = ranked_count, for each entry i in player:
locate the position pos where the entry would be inserted in the ranking array using binary search between position 0 and the current pos inclusive. Make sure you find the smallest entry in case of duplicate scores.
set res[i] to ranking[pos]
free the ranking array
return the res array.
Here is a simple implementation:
int *climbingLeaderboard(int ranked_count, int *ranked,
int player_count, int *player,
int *result_count)
{
if (player_count <= 0) {
*result_count = 0;
return NULL;
}
int *ranking = malloc(sizeof(*ranking) * (ranked_count + 1));
int rank = 1;
ranking[0] = rank;
for (int i = 1; i < ranked_count; i++) {
if (ranked[i] != ranked[i - 1])
rank++;
ranking[i] = rank;
}
ranking[ranked_count] = rank + 1;
int *res = malloc(sizeof(*res) * player_count);
*result_count = player_count;
int pos = ranked_count;
for (int i = 0; i < player_count; i++) {
int start = 0;
while (start < pos) {
int middle = start + (pos - start) / 2;
if (ranked[middle] > player[i])
start = middle + 1;
else
pos = middle;
}
res[i] = ranking[pos];
}
free(ranking);
return res;
}
Look for ways to use "branchless" to improve execution speed:
positions[0]=1;
for(int i=0, j=1; j<newsize; i++, j++){
positions[j]=(ranked[j]<ranked[i])? (positions[i]+1) : positions[i];
}
becomes
positions[0] = 1;
for( int i = 0, j = 1; j < newsize; i++, j++ )
positions[j] = positions[i] + (ranked[j] < ranked[i]);
Other than this, I don't even want to try to sort out what this code is attempting.
I'm working on some basic programs for learning purposes. Struggling to find out logic in this kind of recursion fuction. How does the "loop" inside histogram function works? Is it possible to get rid of it and make it only main function? Any info is appreciate.
The task is to create horizontal histogram with given integers.
#include <stdio.h>
#include <string.h>
void histogram(int numbers[], int length, int n) {
int finished = 1;
for(int i = 0; i < length; i++){
if(numbers[i] - n > 0)
finished = 0;}
if(finished)
return;
else {
histogram(numbers, length, n +1);
int counter = 0;
for(int i = 0; i < length; i++) {
int number = numbers[i] -n;
if(number > 0)
printf("* ");
else
printf(" ");
}
printf("\n");
}
}
int main(void) {
int numbers[] = {1, 3, 1};
int length = sizeof(numbers) / sizeof(int);
histogram(numbers, length,0);
return 0;
}
Each iteration of the recursion is drawing a line of and * character, a horizontal slice of the histogram.
For n-th level the values numbers[i] that are larger or equal than n are marked by *, other become whitespaces.
Note that recursion is called before drawing anything. Thus the deepest level is drawn first:
For example:
numbers[] = {1, 2, 3, 1}
Level3: * \n as 1<3, 2<3, 3>=3, 1<3
Level2: ** \n as 1<2, 2>=2, 3>=2, 1<2
Level1:****\n as 1>=1, 2>=1, 3>=1, 1>=1
Level0:****\n as 1>=0, 2>=0, 3>=0, 1>=0
This recursion can rewritten as two nested loops.
Find maximal height. Set it max_number:
Iterate over heights from max_number to 0 inclusive.
For each height iterate over whole array printing * is numbers[i] >= height, otherwise print
Code:
#include <stdio.h>
void histogram(int numbers[], int length) {
int max_number = 0;
for (int i = 0; i < length; ++i)
if (numbers[i] > max_number)
max_number = numbers[i];
for (int height = max_number; height >= 0; --height) {
for (int i = 0; i < length; ++i)
if (numbers[i] >= height)
putchar('*');
else
putchar(' ');
putchar('\n');
}
}
int main() {
int A[] = {1,2,3,1};
histogram(A, 4);
return 0;
}
produces:
*
**
****
****
to make a horizontal histogram ... just switch the loops.
void horiz_histogram(int numbers[], int length) {
int max_number = 0;
for (int i = 0; i < length; ++i)
if (numbers[i] > max_number)
max_number = numbers[i];
for (int i = 0; i < length; ++i) {
for (int height = max_number; height >= 0; --height)
if (numbers[i] >= height)
putchar('*');
else
putchar(' ');
putchar('\n');
}
}
produces:
**
***
****
**
Imagine drawing a table wide as the length of the array of numbers and high as its maximum value:
// Pseudocode
width = length = sizeof(numbers) / sizeof(int) // = 3
height = max(numbers[] = {1, 3, 1}) // = 3
At each step histogram() checks if it has reached the top of the graph.
If so, it prints the top line and returns.
Otherwise it goes up one line and checks again.
This way histogram() prints the top line first and then the others "climbing down"
so I've been struggling with this example for a good hour now and I can't even begin to process how should I do this.
Write a program that, for given n and m, forms a matrix as described.
The matrix should be m x m, and it's filled "spirally" with it's
beginning in the upper left corner. The first value in the matrix is
the number n. It's repeated until the "edge" of the matrix, at which
point the number increments. After the number 9 goes 0. 0 ≤ n ≤ 9, 0 ≤
m ≤ 9
Some time ago I had made a function to display the numbers 1 to n on an odd-sized grid.
The principle was to start from the center and to shift by ;
x = 1
x box on the right
x box on the bottom
x++
x box on the left
x box at the top
x++
With this simple algorithm, you can easily imagine to maybe start from the center of your problem and decrement your value, it seems easier to start from the center.
Here is the code that illustrates the above solution, to be adapted of course for your problem, it's only a lead.
#define WE 5
void clock(int grid[WE][WE])
{
int count;
int i;
int reach;
int flag;
int tab[2] = {WE / 2, WE / 2}; //x , y
count = 0;
flag = 0;
i = 0;
reach = 1;
grid[tab[1]][tab[0]] = count;
for (int j = 0; j < WE - 1 && grid[0][WE - 1] != pow(WE, 2) - 1; j++)
for (i = 0; i < reach && grid[0][WE - 1] != pow(WE, 2) - 1; i++, reach++)
{
if(flag % 2 == 0)
{
for(int right = 0 ; right < reach ; right++, tab[0]++, count++, flag = 1)
grid[tab[1]][tab[0]] = count;
if(reach < WE - 1)
for(int bottom = 0; bottom < reach; bottom++, count++, tab[1]++)
grid[tab[1]][tab[0]] = count;
}
else
{
for(int left = 0; left < reach; left++, count++, tab[0]--, flag = 0)
grid[tab[1]][tab[0]] = count;
for(int top = 0; top < reach; top++, tab[1]--, count++)
grid[tab[1]][tab[0]] = count;
}
}
}
I finally solved it. If anybody's interested, here's how I did it:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
//Fills the row number "row" with the number n
int fillRow(int m, int n, int arr[m][m], int row)
{
int j;
for(j=0;j<m;j++)
{
if(arr[row][j] == -1 || arr[row][j] == n-1) arr[row][j] = n;
}
}
//Fills the column number "col" with the number n
int fillCol(int m, int n, int arr[m][m], int col)
{
int i;
for(i=0;i<m;i++)
{
if(arr[i][col] == -1 || arr[i][col] == n-1) arr[i][col] = n;
}
}
int main()
{
int n, m, i, j, r=1, c=1, row=-1, col=-1;
scanf("%d %d",&n, &m);
int arr[m][m];
//Fill array with -1 everywhere
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
arr[i][j] = -1;
}
}
//Calculate which row/column to fill (variables row/col)
//Fill row then column then row than column...
for(i=0;i<2*m;i++)
{
if(i%2==0)
{
row = (r%2==0) ? m-r/2 : r/2;
fillRow(m, n, arr, row);
n++;
r++;
}
else if(i%2==1)
{
col = (c%2==0) ? c/2-1 : m-c/2-1;
fillCol(m, n, arr, col);
n++;
c++;
}
}
//If an element is larger than 9, decrease it by 10
//Prints the elements
for(i=0;i<m;i++)
{
for(j=0;j<m;j++)
{
if(arr[i][j]>9) arr[i][j] -=10;
printf("%d ",arr[i][j]);
}
printf("\n");
}
return 0;
}
I am using eclipse 3.2020 on WIN10 and I have a problem executing my main function.
When I run the program as it is, I get no output to conole, even when I add a printf in the first line, and the exit code is -1,073,741,819. When I comment out/ delete the line solve(s); the code run as intended and gives exit code 0.
Edit: added full code (both solve and print_sol are in solver.c)
Edit 2: As mentioned in the comments, the problem was in the code (bug) and not eclipse, I just assumed that an error message will be printed if there is one.
p.s.: I still find the fact a printf in the start won't print if there is a runtime error in another part of the main function quite weird.
main.c:
#include "solver.h"
#include <stdlib.h>
int main(int argc, char** argv){
int **grid = (int**) malloc(sizeof(int*) * 4);
for (int i = 0; i < 4 ; i++){
grid[i] = (int*) malloc(sizeof(int) * 4);
}
int mat[4][4] = {{1,0,3,0}
,{2,0,0,0}
,{3,0,0,0}
,{4,2,0,0}};
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
grid[i][j] = mat[i][j];
}
}
solver *s = create_solver(4, &grid);
solve(s);
print_sol(s);
}
solver.h:
#ifndef SOLVER_H_
#define SOLVER_H_
typedef struct sudoku_solver solver;
/*creates a new solver using the length of one row of the board.
*Then, the user will follow the instructions on screen to input the board*/
solver* create_solver(int row_len, int ***input_board_ptr);
/*if solver is NULL, an error will appear.
*Otherwise, The board that was given won't be changed, and neither
*the solver nor the solution (unless saved before using get_sol)
*will be accessible after this*/
void destroy_solver(solver *solver);
/*if solver is NULL, an error will appear.
*Otherwise, it will solve the inputed board*/
void solve(solver *solver);
/*if "solve" wasn't executed before, an error will appear.
*Otherwise, it will print a solution to the inputed board*/
void print_sol(solver *solver);
/*if "solve" wasn't executed before, an error will appear.
*Otherwise, returns a solution to the inputed board as a matrix of integers*/
int** get_sol(solver *solver);
#endif /* SOLVER_H_ */
solver.c:
#include "solver.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
/*the board will be represented by an array of size NxN.
*the value of every board cell is between 0 and N when 0
*means "default value"*/
typedef struct sudoku_solver{
/*length of one row of the board*/
int N;
/*a pointer to the solution board*/
int ***sol_ptr;
}solver;
solver* create_solver(int row_len, int ***input_board_ptr){
solver *s = (solver*) malloc(sizeof(solver));
/*throw an ERROR if the malloc failed*/
/*row_len is a variable, so we have to declare everything dynamically */
/*allocating the sol matrix as an array of pointers (1 out of 2D)*/
int **sol = (int**) malloc(row_len * sizeof(int*));
for (int i = 0; i < row_len; i++){
/*allocating every row (the second D)
*while making sol equal to input_board*/
sol[i] = (int*) malloc(row_len * sizeof(int));
for (int j = 0; j < row_len; j++){
sol[i][j] = (*input_board_ptr)[i][j];
}
}
s->N = row_len;
/*if row_len != pow(sqrt(row_len),2) then throw invalid input ERROR*/
s->sol_ptr = /
return s;
}
void destroy_solver(solver *s){
for (int i = 0; i < s->N; i++){
free((*(s->sol_ptr))[i]);
}
free(*(s->sol_ptr));
free(s->sol_ptr);
free(s);
}
int* calc_next(int x, int y, int *next, solver *s);
bool isSafe(int x, int y, int val, solver *s);
bool solve_rec(int x, int y, solver *s);
void solve(solver *s){
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
//find next empty space
if ((*sp)[0][0] == 0){
next[0] = 0;
next[1] = 1;
}
else{
calc_next(0, 0, next, s);
}
int nextX = next[0];
int nextY = next[1];
for (int i = 1; i < n; i++){
if (isSafe(nextX, nextY, i, s)){
(*sp)[nextX][nextY] = i;
if(solve_rec(nextX, nextY, s)){
return;
}
//backtrack
(*sp)[nextX][nextY] = 0;
}
}
printf("no sol");
return;
}
bool solve_rec(int x, int y, solver *s){
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
if (x == n - 1 && y == n - 1){
return true;
}
//find next empty space
calc_next(x, y, next, s);
int nextX = next[0];
int nextY = next[1];
for (int i = 1; i < n; i++){
if (isSafe(nextX, nextY, i, s)){
(*sp)[nextX][nextY] = i;
if(solve_rec(nextX, nextY, s)){
return true;
}
//backtrack
(*sp)[nextX][nextY] = 0;
}
}
return false;
}
bool isSafe(int x, int y, int val, solver *s){
int n = s->N;
int ***sp = s->sol_ptr;
/*check row*/
for (int j = 0; j < n; j++){
if ((*sp)[x][j] == val){
return false;
}
}
/*check col*/
for (int i = 0; i < n; i++){
if ((*sp)[i][y] == val){
return false;
}
}
/*check block
*the index of a block in a grid is just like the index of entry in block.
*In sudoku, there are bs*bs blocks, and each has bs rows and bs columns*/
int bs = sqrt(n); // block size
int block_x_index = x / bs;
int block_y_index = y / bs;
for(int i = block_x_index * bs; i < bs * (block_x_index + 1); i++){
for(int j = block_y_index * bs; j < bs * (block_y_index + 1); j++){
if ((*sp)[i][j] == val){
return false;
}
}
}
return true;
}
/*assuming x,y is not the last place in the grid,
* finds the next empty place after it*/
int* calc_next(int x, int y, int *next, solver *s){
int n;
int ***sp = s->sol_ptr;
/*find the first empty place*/
do{
n = s->N;
if (y == n - 1){
x++;
y = 0;
}
else{
y++;
}
}while ((*sp)[x][y] != 0);
next[0] = x;
next[1] = y;
return next;
}
void print_sol(solver *s){
int n = s->N;
int bs = sqrt(n); // block size
char curr;
int rows_passed, col_passed;
for (int i = 0; i < n + bs - 1; i++){
for (int j = 0; j < n + bs - 1; j++){
//if it's a grid row
if (i == bs || ((i - bs) % (bs + 1)) == 0){
//if it's also a grid col
if (j == bs || ((j - bs) % (bs + 1) == 0)){
curr = '+';
}
else{
curr = '-';
}
}
//if it's only a grid col
else if (j == bs || ((j - bs) % (bs + 1) == 0)){
curr = '|';
}
else{
rows_passed = i / (bs + 1);
col_passed = j / (bs + 1);
curr = '0' + (*(s->sol_ptr))[i-rows_passed][j-col_passed];
}
printf("%c",curr);
}
printf("\n");
}
}
int** get_sol(solver *solver){
return *(solver->sol_ptr);
}
Thank you.
Please learn how to use your debugger. In this case, it would take you directly to the problem: you're crashing with an access violation (Windows 0xc0000005) here:
void solve(solver *s) {
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
//find next empty space
if ((*sp)[0][0] == 0) { // <-- Access violation here: "sp" incorrectly initialized!
next[0] = 0;
next[1] = 1;
}
The underlying problem is that although sudoku_solver.N was initialized to "4" ... sudoku_solver.sol_ptr[0][0] is pointing to uninitialized memory.
PS:
Yes, it's very definitely "executing". It wouldn't crash if it didn't run ;)
I'm trying to solve the 8 queens puzzle problem in C. I'm having problems with the recursive search. The program is supposed to start at a given column:
execute(tabuleiro,8,0);
Where the 8 is the number of columns in the board, and 0 is the start column.
This works when I start at column 0. When I send any other column number to the recursive search, the program just counts to the last column. For example, if I choose to start the search from the number 5 column, the code search from the column 5 to 7, after this it should search from 0 to 4, but it doesn't do that.
If I do this:
execute(tabuleiro,8,3);
It fills in only the last 5 colummns, and does not return to column 0 to finish the solution:
Also, how can I select the initial position for the queen in this code? Like I said before, the column is assigned in the code, but I'm not sure how to pick the correct column.
The code has 3 functions: one is to display the board, a second to check if the move is legal (so one queen doesn't attack the other), and the last one to place one queen and recur for the remainder of the board.
#include <stdlib.h>
#include <windows.h>
int sol = 0;
void viewtab(int tab[][8], int N)
{
int i,j;
for( i = 0; i < N; i++)
{
for( j = 0; j < N; j++)
{
if(tab[i][j] == 1)
printf("R\t");
else
printf("-\t");
}
printf("\n\n");
}
printf("\n\n");
system("pause");
printf("\n");
}
int secury(int tab[][8], int N, int lin, int col)
{
// this function is to check if the move is secury
int i, j;
// attack in line
for(i = 0; i < N; i++)
{
if(tab[lin][i] == 1)
return 0;
}
//attack in colune
for(i = 0; i < N; i++)
{
if(tab[i][col] == 1)
return 0;
}
// attack in main diagonal
//
for(i = lin, j = col; i >= 0 && j >= 0; i--, j--)
{
if(tab[i][j] == 1)
return 0;
}
for(i = lin, j = col; i < N && j < N; i++, j++)
{
if(tab[i][j] == 1)
return 0;
}
// attack in main secondary
for(i = lin, j = col; i >= 0 && j < N; i--, j++)
{
if(tab[i][j] == 1)
return 0;
}
for(i = lin, j = col; i < N && j >= 0; i++, j--)
{
if(tab[i][j] == 1)
return 0;
}
// if arrive here the move is secury and return true
return 1;
}
void execute(int tab[][8], int N, int col)
{
int i;
if(col == N)
{
printf("Solution %d ::\n\n", sol + 1);
viewtab(tab, N);
sol++;
return;
}
for( i = 0; i < N; i++)
{
// check if is secury to put the queen at that colune
if(secury(tab, N, i, col))
{
// insert the queen (with 1)
tab[i][col] = 1;
// call recursive
execute(tab, N, col + 1);
// remove queen (backtracking)
tab[i][col] = 0;
}
}
}
int main()
{
int i, j, tabuleiro[8][8];
for (i = 0; i < 8; i = i + 1)
for (j = 0; j < 8; j = j + 1) tabuleiro[i][j] = 0;
execute(tabuleiro,8,0);
return 0;
}
The search always stops in the rightmost column because you specifically tell it to stop there:
void execute(int tab[][8], int N, int col)
{
int i;
if(col == N)
{
printf("Solution %d ::\n\n", sol + 1);
viewtab(tab, N);
sol++;
return;
}
Look at your termination condition: you check the current column against the highest column number, and stop there.
If you want to go back to column 0, you have to change your loop logic. For instance, let col reach N, at which point you reset it to 0, and let it continue until you hit the original value. Another way is to continue until the count of placed queens is N.
You choose the initial point in the same way: you pick the first one and make your recursive call. If that eventually results in a solution, you print it. If not, your top-most call continues to the next row (line) of the board and puts the first queen there.
This is already in your main logic. Just make sure that secury will return true when the board is empty, rather than false or throwing an error.
A. You can place the first Queen at (0,0).
B. And begin the search also from (0,0).
C. I do not see any need to start looking for some other index.
Successfully!!