I was reading this book from Skiena, Programming Challenges and after the backtracking chapter there was a question about solving the 15-puzzle with backtracking, which I reduce it to 8-puzzle just experimenting. I have this recursive code and I am wondering whether it have a chance to find the solution ever. The code is kind of ugly (be warned):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int arr[20][20]={
{3,1,2},
{4,0,5},
{6,8,7}
};
int moveX[20]={1,1,1,0,0,-1,-1,-1};
int moveY[20]={0,1,-1,1,-1,0,1,-1};
int depth=0;
int findRow(){
int i,j;
for(i=0;i<4;i++){
for(j=0;j<4;j++){
if(arr[i][j]==0){
return i;
}
}
}
}
int findCol(){
int i,j;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
if(arr[i][j]==0){
return j;
}
}
}
}
void print(){
int i,j;
for(i=0;i<3;i++){
for(j=0;j<3;j++){
printf("%i ",arr[i][j]);
}
printf("\n");
}
printf("\n");
}
int isReady(){
if(arr[0]==1 && arr[1]==2 && arr[2]==3 && arr[3]==4 && arr[4]==5 && arr[5]==6 && arr[6]==7 && arr[7]==8){
return 1;
}
else return 0;
}
void perm(int row,int col,int n){
if(n>=9){
print();
if(isReady())
printf("Finished");
depth++;
return;
}
int i=0;int diffX,diffY,temp;
int r=findRow();
int c=findCol();
temp=arr[r][c];
arr[r][c]=arr[row][col];
arr[row][col]=temp;
for(i=0;i<8;i++){
diffX=row+moveX[i];
diffY=col+moveY[i];
if(diffX>=0 && diffX<4 && diffY>=0 && diffY<4){
perm(diffX,diffY,n+1);
}
}
temp=arr[r][c];
arr[r][c]=arr[row][col];
arr[row][col]=temp;
}
int main()
{
perm(0,0,0);
return 0;
}
My question is, is there a chance with this code to find the solution and second, can anybody how the puzzle can be solved in reasonable time?
You have five problems. First, the isReady function is incorrect. It should look like this:
int isReady(){
if(arr[0][0]==1 && arr[0][1]==2 && arr[0][2]==3 &&
arr[1][0]==4 && arr[1][1]==5 && arr[1][2]==6 &&
arr[2][0]==7 && arr[2][1]==8){
return 1;
}
else return 0;
}
Second, you are exceeding your puzzle bounds with diffX and diffY. You need to change this:
if(diffX>=0 && diffX<4 && diffY>=0 && diffY<4){
to this:
if(diffX>=0 && diffX<3 && diffY>=0 && diffY<3){
Third, your findRow function also exceeds the puzzle bounds. Change all of the 4 to 3.
Fourth, you should check your victory condition only after you have made your move. So move your victory check below the swap:
temp=arr[r][c];
arr[r][c]=arr[row][col];
arr[row][col]=temp;
// This victory check is now below the move.
if(n>=9){
print();
if(isReady())
printf("Finished");
depth++;
return;
}
Fifth, you should change your initial call from this:
perm(0,0,0);
to this:
perm(1,1,0);
The way you have it, you are always forcing a move to the upper left as your first move. The modified way keeps the 0 in the center so it doesn't force your first move. When I ran this code with all of the modifications I made, it found 3 solutions. When I further modified the code to check for solutions at any depth, it found 2 solutions at depth 8 and 3 solutions at depth 9.
Related
I'm supposed to print a triangle int tri(int rows) in c using recursion without multiplication or loops. The triangle should have one * in the 1st row, two ** in the 2nd row, three *** in the 3rd row and so on...
here's what I tried and what seems to work in other peoples code, but not in mine. I sadly cannot see the error yet:
#include <stdio.h>
int triangle(int rows){
if(rows >= 0){
return 0;
}
else if(rows == 1){
printf("*");
return 1;
}
else{
printf("*");
return rows + triangle(rows-1) ;
}
}
int main()
{
triangle(5);
return 0;
}
I'm guessing it has something to do with the printing part, I thought about making an own variable for that but since I'm not allowed to use multiplication, I don't know how I could describe it. I want to know what my logical problem is right here and how I could solve it easily.
Imagine that you had a function void line(n) that prints n asterisks on one line.
Then you could write
void triangle(int n)
{
// Print the smaller triangle first, if there should be one.
if (n > 0)
{
triangle(n-1);
}
// Then add the last line after the smaller triangle.
line(n);
}
All that remains is to add the lines:
void line(int n)
{
if (n <= 0)
{
// End of line.
printf("\n");
}
else
{
// Print an asterisk, and then the rest of the line.
printf("*");
line(n-1);
}
}
Here's a slightly different version which uses just one set of recursive calls.
The second recursive call is replaced by using the printf statement to simply output the desired number of stars on each line.
/* triangle.c */
#include <stdio.h>
void triangle(int num)
{
if (num > 1) {
triangle(num - 1);
}
printf("%.*s\n", num, "****************");
}
int main (void)
{
triangle(16);
return 0;
}
I am a beginner to arrays in recursion so need some guidance.
I am trying to find whether an element is present in an array or not.
// Program to find whether an element exist in an array or not.
#include <stdio.h>
int arr[5]= {1,2,3,4,5};
int fooSearch(int array1[],int N,int i, int X)
{
if(i==N)
return 0;
else if (array1[i]==X)
return 1;
else
return fooSearch(array1,N,i++,X);
}
// N denotes total size 5
// i counter that moves from 0 to 4 and eliminate recursion when it reaches 5
// X is the element to be found
int main() {
fooSearch(arr,5,0,3);
return 0;
}
The error I obtained is Segmentation Fault (SIGSEGV).
Please guide me what wrong I am doing with this code.
i++ is a post-fix increment, which increments i after the expression containing it is evaluated. Thus, every call to fooSearch effectively becomes to fooSearch(array1, N, 0, X). Recursion is endless, hence the segfault (or a stack-overflow on my compiler). (You can confirm that i is unchanging by placing printf("%d\n", i) at the top of the function.)
Fix this by using pre-fix increments, which increment the variable before evaluation.
return fooSearch(array1, N, ++i, X);
Or use i+1, since you won't be reusing the local variable anyways.
return fooSearch(array1, N, i+1, X);
While calling fooSearch() recursively pass i+1 instead of i++ as post increment i++ doesn't change i in the argument. For e.g
fooSearch(array1,N,i+1,X);
to find whether an element is present in an array or not.
you can initialize number of array elements, Let's say 10 elements:
int num[10]= {2,3,5,6,1,8,4,9,0,7};
Then, Creating for loop for checking if number 9 is not in array then continue until the condition is false then print the element location.
for(i=0; i<10; i++){
if(num[i] != 9){
continue;
}
printf("9 is found here\n%d",i);
break;
}
At the end, You write an if condition to check if the loop is ended and print not found.
if(i==10){
printf("Not Found");
}
The full code is here:
#include <stdio.h>
int num[10]={2,3,5,6,1,8,4,9,0,7};
int i;
int main(void){
for(i=0; i<10; i++){
if(num[i] != 9){
continue;
}
printf("9 is found here\n%d",i);
break;
}
if(i==10){
printf("Not Found");
}
getchar();
return 0;
}
You have to use ++i or i+1 instead of i++.
i++ is a post increment operator, so the value of i that will go to the function will not change.
Just use ++i or i+1 and you will get the answer.
public static boolean checkNumber(int input[], int x) {
int n=input.length;
if(n==0)
return false;
if(input[0]==x)
{
return true;
}
int small[]=new int[n-1];
for(int i=1;i<n;i++)
{
small[i-1]=input[i];
}
return checkNumber(small, x);
}
// Program to find whether an element exist in an array or not.
// Number of elements of array is N, the number to search is X
#include <stdio.h>
int arr[]= {1,2,3,4,5};
int fooSearch(int array1[],int N,int i, int X)
{ if(i==N)
return 0;
else if (array1[i]==X)
return 1;
else
i=i+1;
return fooSearch(array1,N,i,X);
}
int main() {
int x = fooSearch(arr,5,0,9);
printf("%d",x);
return 0;
}
This is a simple code just to illustrate the issue I am dealing with.
If you give the input of n = 3 and enter the array elements as 1, 2 ,3 and m= 0 the program crashes!!!
Why is it so?? The problem occurs due to the last 2 lines involving the free()
Now my question is why this thing is happening? The same program with the same input doesn't crash if the free statements are removed...
Please explain me. Is it so that the conditional memory allocation is causing the said problem to occur?? If so then why ?
I am not getting any cue, moreover free (NULL) shall not cause any error as far as I know, so the problem is caused when I am trying to free one of the allocated memory, especially positive in my input ...
This is my code:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int n;
scanf("%d",&n);
printf("Enter elements into the array\n");
int arr[n];
int i;
for(i=0;i<n;)
{
printf("arr[%d] ? ",i);
scanf("%d",(arr+i));
if(i>0)
{
if(arr[i]<arr[i-1])
continue;
else
i++;
}
else
i++;
}
int m;
printf("m ? ");
scanf("%d",&m);
int j,flag=0;
int *positive,*negative;
int start,end;
start=arr[0];
end=arr[n-1];
if(start<0 && end<0)
{
negative=(int*)calloc((start*-1),sizeof(int));
positive=0;
}
else if(start<0 && end>0)
{
negative=(int*)calloc((start*-1),sizeof(int));
positive=(int*)calloc(end,sizeof(int));
}
else if(start>=0 && end >0)
{
negative=0;
positive=(int*)calloc(end,sizeof(int));
}
int p=0;
for(i=0;i<n;i++)
{
if(i==0)
p=-1;
else
p=i;
if(arr[i]<0)
negative[-arr[i]]=p;
else
positive[arr[i]]=p;
}
for(i=0;i<n;i++)
{
int num=m-arr[i];
if(negative!=0 && num<0 && negative[-num])
{
if(negative[-num]==-1)
j=0;
else
j=negative[-num];
printf("%d %d\n",i,j);
flag=1;
}
else if(positive!=0 && num>=0 && positive[num])
{
if(positive[num]==-1)
j=0;
else
j=positive[num];
printf("%d %d\n",i,j);
flag=1;
}
}
if(flag==0)
printf("NO SUCH i j EXISTS\n");
if(positive) free(positive);
if(negative) free(negative);
return 0;
}
Here is my output:
With the input values you mention, you first do :
end=arr[n-1];
positive=(int*)calloc(end,sizeof(int));
Given that n == 3 and arr[n-1] == 3, you allocate an array of 3 ints for positive.
In the very next loop, you then end up doing :
positive[arr[i]]=p;
which tries to overwrite positive[3] (when i == n-1). This is trying to write beyond the bounds of the array (valid indexes range from 0 to 2 only), and undefined behavior ensues, meaning anything at all can happen after that point, including a crash.
Okay so I have been working on a small rouge like game to teach myself c however I cannot figure out why the array's end up changing randomly after initialization. Here is the code I have:
// ConsoleApplication2.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <stdio.h>
#include <conio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
const int x=10;
const int y=10;
int rexit[]={5,5};
int player[]={1,1};
int enemy[]={x,y};
int useless[]={1,1};
/*
int getinput(int len){
char temp[100];
return(atoi(strtok(fgets(temp,len+1,stdin),"\n")));
}
*/
void bad(){
float bob;
float temp[8]={1,1};
temp[1]=player[1]-enemy[1];
temp[2]=player[2]-enemy[2];
bob=pow(temp[1],2)+pow(temp[2],2);
printf("%f\n",bob);
if (sqrt(bob)<=5){
if (abs(player[1]-enemy[1])>abs(player[2]-enemy[2])){
if (player[1]-enemy[1]<0 && enemy[1]-1>=0){
enemy[1]=enemy[1]-1;
}
else if (enemy[1]+1<=x && player[1]-enemy[1]!=0){
enemy[1]=enemy[1]+1;
}
}
else;
if (player[2]-enemy[2]<0 && enemy[2]-1>=0){
enemy[2]=enemy[2]-1;
}
else if (enemy[2]+1<=y && enemy[2]-player[2]!=0){
enemy[2]=enemy[2]+1;
}
}
}
void map() {
int s;
int a;
bad();
printf("%i %i\n",rexit[1],rexit[2]);
printf("+");
for (a=0;a<=x;a++){
printf("-");
}
printf("+\n");
for (s=0;s<=y;s++){
printf("|");
for (a=0;a<=x;a++){
if ((player[1]==rexit[1] && player[2]==rexit[2]) || (player[1]==enemy[1] & player[2]==enemy[2])){
exit(EXIT_SUCCESS);
}
else if (rexit[1]==s && rexit[2]==a){
printf("E");
}
else if (player[1]==s && player[2]==a){
printf("*");
}
else if (enemy[1]==s && enemy[2]==a){
printf("#");
}
else{
printf(".");
}
}
printf("|\n");
}
printf("+");
for (a=0;a<=x;a++){
printf("-");
}
printf("+\n");
}
void move(){
char me=_getch();
int temp=0;
me=toupper(me);
if (me=='W'){ player[1]=player[1]-1; if (player[1]<=0) player[1]=0;}
else if (me=='S'){ player[1]=player[1]+1; if (player[1]>=y) player[1]=y;}
else if (me=='A'){ player[2]=player[2]-1; if (player[2]<=0) player[2]=0;}
else if (me=='D'){ player[2]=player[2]+1; if (player[2]>=x) player[2]=x;}
else {temp=1;}
if (temp==1){
move();}
else{
system("cls");
map();}
}
void circle(char c,int x)
{
int i,j;
for(i=-x;i<x;i++)
{
for(j=-x;j<x;j++)
{
if(i*i+j*j<x*x)
printf("%c",c);
else
printf(" ");
}
printf("\n");
}
}
void main(){
printf("%i %i\n",enemy[1],enemy[2]);
printf("%i %i\n",useless[1],useless[2]);
system("title BioGames");
system("color A"); // the colours are from 1 to 15
map();
while (true){
move();
}
}
You are treating your array indexing as 1-based. Arrays in C are 0-based.
For example, you declare:
int player[]={1,1};
The only valid indices for this array are 0 and 1 (ie player[0] and player[1]).
There is no such thing as player[2] - that is accessing memory outside the array bounds. This is probably why you think your arrays are changing randomly. They are either being affected by out-of-bound writes to other arrays, or you are simply experiencing undefined behaviour.
Your arrays useless and enemy are declared to contain two values each at initialization. Your main is printing array indices 1 and 2. In C, however, array indices start at 0. So you should be printing indices 0 and 1.
Assume a 2D [n][n] matrix containint only 1's and 0's. All the 1's in any row should come before 0's. The number of 1's in any row i should be at least the no, of 1's row (i+1). Find a method and write a c program to count the no of 1's in a 2D matrix. The complexity of the algorithm should be O(n).
The question is from Cormen's Algorithm Book, and below is my implementation for this problem. Kindly point out the mistakes in my algorithm and/or perhaps suggest a better way. Thanks!
#include <stdio.h>
#include <stdlib.h>
int **map;
int getMatrix();
main()
{
int n,i,j,t;
j=0;
n=getMatrix();
i=n-1;
int sum[n];
for(t=0;t<n;t++)
sum[t]=0;
int count=0;
while ( (i>=0) && (j<n) )
{
if ( map[i][j] == 1 )
{
j++;
count=count+1;
}
else
{
if (i==(n-1))
{
sum[i]=count;
count=0;
i--;
}
else
{
sum[i]=sum[i+1]+count;
count=0;
i--;
}
}
}
for (t=0;t<n;t++)
{
if ((t==(n-1)) && (sum[t]==0))
sum[t]=0;
else if ((sum[t]==0) && (sum[t+1]>0))
sum[t]=sum[t+1];
}
int s=0;
for (t=0;t<n;t++)
s=s+sum[t];
printf("\nThe No of 1's in the given matrix is %d \n" ,s);
}
int getMatrix()
{
FILE *input=fopen("matrix.txt","r");
char c;
int nVer=0,i,j;
while((c=getc(input))!='\n')
if(c>='0' && c<='9')
nVer++;
map=malloc(nVer*sizeof(int*));
rewind(input);
for(i=0;i<nVer;i++)
{
map[i]=malloc(nVer*sizeof(int));
for(j=0;j<nVer;j++)
{
do
{
c=getc(input);
}while(!(c>='0' && c<='9'));
map[i][j]=c-'0';
}
}
fclose(input);
return nVer;
}
it is easier to find problem when you first describe what you want to do.
Anyway, seems to me that you have a problem on the if, you set
i == (n-1), on the initialization phase, and each time you enter this if the statmnet is correct and you don;t reduce i,
if (i==(n-1))
{
sum[i]=count;
count=0;
**i--;**
}
else
{
sum[i]=sum[i+1]+count;
count=0;
i--;
}