So I have to do a modified version of the N queen problem, where we are given an initial configuration of the chess board filled with pawns, and we need to find the maximum number of queens we can have so that they don't attack each other. The input consists of an integer in the first line giving the dimension of the board ( NxN) and n lines defining the setup of the chess board.The characters will be either a āpā (meaning there is already a pawn in that location) or an āeā (meaning that location is empty).
For example, for this input,
5
epepe
ppppp
epepe
ppppp
epepe
the output will be 9.
Here is my code, everything seems clear, but I don't see why it doesnt give the correct output
#include <stdio.h>
#include <malloc.h>
/* function headers */
void do_case(int);
int solve(char **,int,int);
int canPlace(char **,int,int,int);
/* Global vars */
int queens;
int main(void)
{
int n;
scanf("%d",&n);
getchar();
while( n != 0 )
{
do_case(n);
scanf("%d",&n);
getchar();
}
return 0;
}
void do_case(int n)
{
int i,j; //counters for input
//board configuration allocation
char **configuration = (char **)malloc(n*sizeof(char *));
for(i = 0 ; i < n ;i++ )
configuration[i] =(char *)malloc(n*sizeof(char));
queens = 0;
//get input
for( i = 0; i < n; i++ )
{
for( j = 0; j < n; j++ )
{
scanf("%c",&configuration[i][j]);
}
getchar();
}
//solve
solve(configuration,n,0);
printf("%d \n",queens);
}
//recursive solver
int solve(char **configuration,int N,int col)
{
int i,j;
//base case
if( col >= N )
return 1;
//consider this column
//try placing queen in non blocked spot in all rows
for(i = 0; i < N; i++)
{
if ( configuration[i][col] == 'e' && canPlace(configuration,N,i,col) )
{
//Place queen in configuration[i][col]
configuration[i][col] = 'q';
queens++;
//recursion on the rest
if( solve(configuration,N,col + 1) == 1 )
{
return 1;
}
//backtrack
configuration[i][col] = 'e';
queens--;
}
}
return 0;
}
//this function check if queen can be placed
int canPlace(char **configuration,int N, int row, int col)
{
int i, j;
/* Check this row on left side */
for (i = 0; i < col; i++)
{
if (configuration[row][i] == 'q')
{
return 0;
}
}
/* Check upper diagonal on left side */
for (i = row, j = col; i >= 0 && j >= 0; i--, j--)
{
if ( configuration[i][j] == 'q')
{
return 0;
}
}
/* Check lower diagonal on left side */
for (i = row, j = col; j >= 0 && i < N; i++, j--)
{
if (configuration[i][j] == 'q')
{
return 0;
}
}
return 1;
}
Basically, your code outputs 0 because it requires that we place exactly one queen in every column, which is not the case in your example.
That said, there are multiple problems with the algorithm (and I don't claim the list is complete, though it may be):
The code does not consider every possibility: it will only find the first possible arrangement, and then quit searching after a single "if( col >= N ) return 1;". Instead, it should go like "if( col >= N ) update the best possible value of queens in a separate variable, then return 0 to continue searching".
In the line "if( solve(configuration,N,col + 1) == 1 )", the code assumes there can not be two queens in a single column. The call should use col instead of col + 1, and somehow account for where we stopped at the current column.
To allow columns without queens, an unconditional call to "solve(configuration,N,col + 1)" should be placed somewhere in the solve function.
When we allow item 2, the function canPlace should be modified to also check the column.
The loops of canPlace should break whenever a pawn is found.
With pawns blocking the way, you shouldn't just move on to the next column because you can place more queens in the same column. You should modify your code to pass both a row and a column when you recurse, and only move to the next square, not the next column.
Also, it looks like your algorithm finds the first solution instead of the best solution. The original queens problem only cared about 1 possible solution, but with the modified problem, you need to make sure you check all solutions and remember the best one.
Also, your canPlace function is wrong. It doesn't account for pawns at all.
Related
try to input 20 numbers with array and to output
the numbers in the double location only but somehow it's print
also the 0 location... please help.
#include<stdio.h>
#define n 20
int main()
{
int num[n]={0},i=0,order=1,double_locaion=0;
for(i=0;i<n;i++)
{
printf("please enter %d number\n",order);
scanf("%d",&num[i]);
order++;
}
for(i=0;i<n;i++)
{
if (i%2==0 && i!=1 && i!=0)
{
printf("%d\n",num[i]);
}
}
}
Try this, start with 2 and increase by 2 every time, the you don't have to deal with 0th element and odd element.
for (i = 2; i < n; i += 2)
{
printf("%d\n",num[i]);
}
First of all there is no way that your code is printing the 0-th location of the array. That's impossible given the condition of the if statement.
Secondly n- you don;t need to use macro expansion for that name.
/* This program takes 20 integer number from input.
* Prints the numbers entered in odd positions.(First,Third,..etc).
*/
#include<stdio.h>
#include<stdlib.h>
#define NUM 20
int main(void)
{
int numArr[NUM];
for(size_t i = 0; i < NUM; i++) {
printf("please enter %zu number\n",i+1);
if( scanf("%d",&numArr[i]) != 1){
fprintf(stderr, "%s\n","Error in input" );
exit(1);
}
}
for(size_t i = 0; i < n; i++)
{
if( i%2 == 0 )// if you want to omit the first number put the
// the condition (i%2 == 0 && i)
{
printf("%d\n",numArr[i]);
}
}
return 0;
}
What you did wrong that your code skipped 0th element?
if (i%2==0 && i!=1 && i!=0)
^^^^
i when 0 makes this condition false - and you never get to print it.
i!=1 ?
If i=1 then i%2 will be 1, so you will not even check the second conditions, the whole conditional expression will become false. So you can safely omit this logic.
Is there a better way?
Sure,
for(size_t i = 0; i < n; i += 2){
printf("%d\n",num[i]);
}
Explanation
If you consider that every time you check the modular arithmetic of 2 the elements which results to 0 remained are
0,2,4,6,8,10,...18
See the pattern? Starts with 0 and increments by 2 each time and when does it stop? Yes before reaching 20 coding it we get
for(size_t i = 0; i < n; i += 2){
/* Initialize with i=0 as first number is 0 (i=0)
* Increments by 2 (i+=2)
* Runs when less than 20 (i<n)
*/
printf("%d\n",num[i]);
}
If you want to omit the 0-th index do initialize properly
for(size_t i = 2; i < n; i += 2){
If you mean you want the numbers from array that are present at even position than you can do like this:
for (i = 2; i < n; i=i + 2) //Initialize i = 0 if 0 is consider as even
{
printf("%d\n",arr[i]);
}
I above code i is initialized to 2 and the increment in each iteration is 2 so it will access elements only at even position (2,4,6...).
I've just started studying information technologies and I am currently stuck on a programming assignment.
I have to write a code in C which displays a cross to the console, the size of the cross being determined by an initial input.
So the console output should look like this:
size?: 5(user input)
xooox
oxoxo
ooxoo
oxoxo
xooox
(replace the os with blank space)
I've now come as far as this:
#include <stdio.h>
int main(void)
{
int n;
printf("size?: ");
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if( (i==j) )
printf("*");
else
printf(" ");
}
printf("\n");
}
return 0;
}
But this only displays one diagonal of the cross, I'm thinking that the opposite diagonal can be created by another condition after the if however I am lost as to what that condition might be.
You're definitely on the right track! Don't give up.
The way to think about this is to think about the loop counters. You've figured out one half of it. If the row and column are the same, you need to output a *. So what's the other condition? Well, think about counting backwards. If the row is the same as the column counted backwards, we also want a *.
I don't want to do your homework for you, so I'll hold off on writing the code, but hopefully that gives you a hint as to what you need to do.
Replace if( (i==j) ) with if( (i==j)||(i+j)==n+1 ), That is,:
#include <stdio.h>
int main(void)
{
int n;
printf("size?: ");
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if( (i==j)||(i+j)==n+1 )
printf("*");
else
printf(" ");
}
printf("\n");
}
return 0;
}
Should you need some help, you have to check the column from the other side as well:
#include <stdio.h>
int n;
int main(void) {
printf("size?: ");
scanf("%d",&n);
for(int i = 1; i <= n; i++) {
for(int j = 1; j <= n; j++) {
if (i == j || i == n - j + 1) printf("*");
else printf(" ");
}
printf("\n");
}
return 0;
}
Edit: There are suggestions to do i + j == n + 1, but I believe i == n - j + 1 makes more sense, since:
i is your current row
j is your current column
n is the size of your square (max row / max column)
i == n - j + 1 means draw * at max - current + 1 column
First thing's first, C compilers don't like
for (int i = 0; i < n; i++)
They like
int i = 0;
for (i = 0; i < n; i++)
But if you're using a C++ compiler, you probably won't get that problem.
Now; back to solving the problem at hand!
On the line:
if( (i==j) )
With this conditional, you're plotting points at (1, 1), (2, 2), (3, 3) ...
You want to also plot points at (1, n), (2, n - 1), (3, n - 2) ...
So you need to add a second conditional to this if statement:
if ( (i==j) || (i == (n - j) + 1 ) )
Then you can simplify this up a bit if you want...
if ( (i==j) || (i == n - j + 1 ) )
And there you go! It now prints a cross, like you described in your question.
I'm trying to populate a 20x20 matrix where each entry is of structure type. My goal is to randomly assign 100 ants and 5 doodlebugs on this 2D array. Even though I got it to work, I don't always get the amount of ants or doodlebugs I need in the matrix. I added a counting function to always verify how many of them I have each time I run the program, but I'm always slightly short. I'm trying to force those number to work (100 ants and 5 doodlebugs) by using a do/while loop in my populating function, although it's not working. Can someone spot where is my logic is failing me?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#define N 20
struct cellState {
int emptyInt;
int antInt;
int dBInt;
char emptyChar;
char antChar;
char dBChar;
};
struct cellState gridState[N][N];
// function to populate world
void pop_mtx(struct cellState gridState[N][N], int antsNeeded, int dBNeeded) {
int i, j;
do {
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if ((gridState[i][j].emptyInt = rand() % 3) == 0) {
gridState[i][j].emptyChar = '.';
} else
if (((gridState[i][j].antInt = rand() % 3 == 1) && antsNeeded != 0)) {
gridState[i][j].antChar = 'a';
antsNeeded--;
} else
if (((gridState[i][j].dBInt = rand() % 3 == 2) && dBNeeded != 0)) {
gridState[i][j].dBChar = 'D';
dBNeeded--;
}
}
}
} while (dBNeeded != 0 && antsNeeded != 0);
}
//function to display current state of the world
void display_mtx(struct cellState gridState[N][N]) {
int i, j;
char charToDisplay;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (gridState[i][j].antChar == 'a')
charToDisplay = 'a';
else
if (gridState[i][j].dBChar == 'D')
charToDisplay = 'D';
else
charToDisplay = '.';
printf("%c ", charToDisplay);
}
printf("\n");
}
printf("\n\n");
}
//function to count ants and doodlebugs
void count_mtx(struct cellState gridState[N][N]) {
int i, j, antCount = 0, dBcount = 0;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
if (gridState[i][j].antChar == 'a')
antCount++;
else
if (gridState[i][j].dBChar == 'D')
dBcount++;
}
}
printf("ant count: %i, doodlebug count: %i\n", antCount, dBcount);
}
int main(void) {
srand((unsigned int)time(NULL));
//populate grid state with 5 doodlebugs and 100 ants
int antsNeeded = 100, dBNeeded = 5;
pop_mtx(gridState, antsNeeded, dBNeeded);
count_mtx(gridState);
display_mtx(gridState);
}
There are several problems. First, each time you call rand() you obtain a different value, so it is possible that none of the three tests pass. You should call rand () once and save the value.
Second, there is nothing that guarantees that over NxN calls of rand() you will get as many ones and twos as you need. The outer loop is therefore necessary. You should also preserve already populated squares from one iteration to the next because it might take a long time before you reach an iteration that produces enough ones and twos.
Third, this method is biased toward the squares at the beginning of the grid. It will not give you one out of all possible distributions of 100 ants and 5 doodlebugs over 400 squares with equal probability.
Here is the proper way to do it:
Consider the grid as a uni-dimensional array. First fill it, in order, with 100 ants, 5 doodlebugs, and empty spaces. Then perform a random shuffle of the array.
This procedure will return each possible distribution of the ants and doodlebugs on the grid with equal probability.
I was solving the N Queen problem where we need to place N queens on a N X N chess board such that no two queens can attack each other.
#include <stdio.h>
#include <stdlib.h>
#include<math.h>
int size=8;
char arr[8][8];
int i,j;
void initializeBoard()
{
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
arr[i][j]='.';
}
}
}
void printArray()
{
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
printf("%c\t",arr[i][j]);
}
printf("\n");
}
printf("\n\n");
}
void placeQueen(int i,int j)
{
arr[i][j]='Q';
}
int isAvailable(int i,int j)
{
int m,n,flag;
for(m=0;m<i;m++)
{
for(n=0;n<size;n++)
{
int k=abs(i-m);
int l=abs(j-n);
if(arr[m][j]!='Q' && arr[k][l]!='Q')
{
flag=1;
}
else
{
flag=0;
break;
}
}
}
return flag;
}
int main(void)
{
initializeBoard();
for(i=0;i<size;i++)
{
for(j=0;j<size;j++)
{
if(isAvailable(i,j)==1)
{
// means that particular position is available
// and so we place the queen there
placeQueen(i,j);
break;
}
}
}
printArray();
return 0;
}
I think the problem is with the isAvailable() method. However, I am not able to find the bug. Please help me identify it.
Is the approach that i am taking involves backtracking ? If not, please provide the same with some explanations
Having done this problem before, not all placements will allow for a valid solution to the problem.
Your solution involves always placing a queen at position (0,0) which will always be available.
You will need to either involve backtracking whenever you go through everything and can't find anything, or you will need to rely on a solution that places all queen's randomly and checking for a solution then (this method is actually much faster than you would think, but at the same time, random therefore very inefficient in the average case)
a potential pseudo solution:
while(!AllQueensPlaced){
for(going through the array ){
if(isAvailable())
{
placeQueen();
lastQueenPlaced = some logical location of last queen;
}
}
if(!AllQueensPlaced)
{
backtrack(lastQueenPlaced);
}
}
Your backtrack method should mark the lastQueenPlaced as dirty and traverse through the array again looking for a new location, and then go through the while loop again. don't forget to change lastQueenPlaced in backtrack() in case that is also a lastQueenPlaced.
Your approach does not backtrack. It iterates over some possibilities, not all. This problems is best solved recursively, so I wouldn't do it as you are doing. You have to define the rules for a Queen being attacked by other. You do it using ifs, and recursion to apply the rule again and to iterate. Most of the backtracking algorithms are written recursively.
I will give you an answer, so you can base yours on mine.
#include <stdio.h>
#include <stdlib.h>
int count = 0;
void solve(int n, int col, int *hist)
{
int i, j;
if (col == n) {
printf("\nNo. %d\n-----\n", ++count);
for (i = 0; i < n; i++, putchar('\n'))
for (j = 0; j < n; j++)
putchar(j == hist[i] ? 'Q' : ((i + j) & 1) ? ' ' : '.');
return;
}
# define attack(i, j) (hist[j] == i || abs(hist[j] - i) == col - j)
for (int i = 0, j = 0; i < n; i++) {
for (j = 0; j < col && !attack(i, j); j++);
if (j < col) continue;
hist[col] = i;
solve(n, col + 1, hist);
}
}
int main(int n, char **argv)
{
if (n <= 1 || (n = atoi(argv[1])) <= 0) n = 8;
int hist[n];
solve(n, 0, hist);
}
The way backtracking works in the following:
create a constraint (a rule) to check if the conditions are meet.
Consider the problem as a search tree. The time spent to search this tree is based on n, the size of the board. The best way to search is recursively, so have in mind, the smart way to solve is using recursion.
In that code, the first set of for loops just prints the board out, and checks if Q if found.
# define attack(i, j) (hist[j] == i || abs(hist[j] - i) == col - j) is my rule, which asserts 2 queens are not attacking each other.
The second set of for loops finds a condition which another queen can be inserted, within the constraint rules.
Then I call find function again. That's how the backtracking is done.
My base case is that 2 queens can be on the board, then I'm going recursively check if another queen can be added until 8. Thus, 2 + 1 = (1+1) + 1 = 1 (1 + 1). Applying the rule again, we have 3 + 1 = (2) + 1 + 1 = (2) + (1 + 1), and again 4 = (3) + 1 + 1 = (3) + (1+1).
Recursion does that for you. Let out apply the rule over and over. So f(n+1) = f(n) + 1 for that case and f(2) = 2 is my base case.
The base of backtracking is if one of those branches don't work out, you can go one level up and search another branch, and so on, until the tree is all searched out. Again, recursion is the way to go.
use a single dimensional array to keep track of the column in which queen can be placed in each row.
the conditions when the queen can be threatened can be formualted as
1) ColumnForRow[i] == ColumnForRow[j] - they will be in the same column
2) (ColumnForRow[i] - ColumnForRow[j] ) == ( i- j) or
(ColumnForRow[j] - ColumnForRow[i]) == (i - j) - they will be on the same diagonal.
public class NQueenSolver {
static int BOARD_SIZE = 15;
static int count = 0;
static int columnForRow[] = new int[BOARD_SIZE];
public static void main(String[] args) {
PlaceQueen(0);
System.out.println(count);
}
static boolean check(int row) {
for (int i = 0; i < row; i++) {
int diff = Math.abs(columnForRow[i] - columnForRow[row]);
if (diff == 0 || diff == row - i)
return false;
}
return true;
}
static void PlaceQueen(int row) {
if (row == BOARD_SIZE) {
printBoard();
++count;
return;
}
for (int i = 0; i < BOARD_SIZE; i++) {
columnForRow[row] = i;
if (check(row)) {
PlaceQueen(row + 1);
}
}
}
private static void printBoard() {
//System.out.println(Arrays.toString(columnForRow));
for (int i = 0; i < BOARD_SIZE; i++) {
for (int j = 0; j < BOARD_SIZE; j++) {
if (columnForRow[i] == j)
System.out.print("Q ");
else
System.out.print("* ");
}
System.out.println();
}
System.out.println();
}
}
Your code has no recursive method, which is the first thought that should pop in head while designing a backtracking algorithm. Thus, you aren't implementing any backtracking strategy here.
Your function isAvailable() is incomplete in many ways.
To check whether a cell (row,column) is under attack or not from already placed queens, you could use the following strategy.
Points to note:
Placing queens row by row
To place queen in ith row, we need to check conflict with queens placed in 0 to (i-1)th rows.
Queen attacks horizontally, vertically and diagonally.
Code (Reference: Tushar Roy's Lecture/Code)
boolean isSafe = true;
for(int queen = 0; queen<row; queen++) // Checking with already placed queens
{
// attack condition
if(position[queen].column == column || position[queen].row +
position[queen].column == row + column || position[queen].row -
position[queen].column == row-column)
{
isSafe = false;
break;
}
}
Hope this helps.
/*
Program to calculate trip and plan flights
*/
#define TRIP 6
#define DEST 1
#include <stdio.h>
int main(void)
{
int type_num, cont_num, index, i, dest_code, trip_num, row, col;
int travelint[TRIP][DEST]= {{0}};
printf("Please enter the number of trips:");
scanf("%d", &trip_num);
for (i=0; i < trip_num ; i++)
{
printf("Please enter destination code:");
scanf("%d", &dest_code);
cont_num = dest_code / 10000;
type_num = dest_code/1000 - cont_num*10;
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
dest_code = travelint[i][0];
else
printf("Invalid code\n");
}
printf("%2d", travelint[0][0]);
return 0;
}
I'm having trouble printing from the array I'm not sure if I'm either printing it wrong or that the number isn't actually being assign in the array. I'm still having trouble with the concept of assign values from input into the array..
An array dimension with only one element in the row is a trifle pointless. You normally only use dimensions with more than one element in each row.
Additionally, you are never assigning to the travelint array - only reading from it. So, since it is initialized to all zeroes, all you will ever see when you print it are zeroes.
You probably simply need to change this:
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
dest_code = travelint[i][0];
to:
if ( (cont_num <= 7) && (cont_num > 0) && (type_num <= 5) && (type_num >=0) )
travelint[i][0] = dest_code;
This assigns to travelint.
To print out a full 2D array, you would normally use:
for (int j = 0; j < TRIP; j++)
{
for (int k = 0; k < DEST; k++)
printf("Trip[%d][%d] = %d\n", j, k, travelint[j][k]);
}
Given that the inner loop will be executed just once per iteration of the outer loop (in your example, where DEST is 1), you could simplify that to:
for (int j = 0; j < TRIP; j++)
{
printf("Trip[%d][%d] = %d\n", j, 0, travelint[j][0]);
}
You should validate the trip_num after the user enters it. You should check that scanf() actually converted a value; if the user types 'A', then your program will go into a rapid loop printing out "Invalid code" every time. Always check that inputs succeed. In theory, you should also check that outputs succeed, but that rule is more often ignored than honoured. Also, if the user is nasty and types 200, then your program is not going to be happy after the user enters the sixth trip destination. It should be between 0 and TRIP (inclusive), of course. You should handle the degenerate (0) case properly, of course. And the printing loop becomes:
for (int j = 0; j < trip_num; j++)
{
printf("Trip[%d][%d] = %d\n", j, 0, travelint[j][0]);
}