CS50 Pset3 function "Won" - c

I am at the last part of the pset, and whenever I check my answer using ./fifteen 3 < ~cs50/pset3/3x3.txt , the program doesn't seem to be comparing my solved puzzle with my win[][] array . End result is that I have made an illegal move.
Could this be a problem that board[i][j]==win[i][j] are comparing addresses instead of the values? All help are appreciated
/**
* fifteen.c
*
* Computer Science 50
* Problem Set 3
*
* Implements the Game of Fifteen (generalized to d x d).
*
* Usage: ./fifteen d
*
* whereby the board's dimensions are to be d x d,
* where d must be in [MIN,MAX]
*
* Note that usleep is obsolete, but it offers more granularity than
* sleep and is simpler to use than nanosleep; `man usleep` for more.
*/
#define _XOPEN_SOURCE 500
#include <cs50.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
// board's minimal dimension
#define MIN 3
// board's maximal dimension
#define MAX 9
// board, whereby board[i][j] represents row i and column j
int board[MAX][MAX];
// board's dimension
int d;
// prototypes
void clear(void);
void greet(void);
void init(void);
void draw(void);
bool move(int tile);
bool won(void);
void save(void);
int main(int argc, string argv[])
{
// greet player
greet();
// ensure proper usage
if (argc != 2)
{
printf("Usage: ./fifteen d\n");
return 1;
}
// ensure valid dimensions
d = atoi(argv[1]);
if (d < MIN || d > MAX)
{
printf("Board must be between %i x %i and %i x %i, inclusive.\n",
MIN, MIN, MAX, MAX);
return 2;
}
// initialize the board
init();
// accept moves until game is won
while (true)
{
// clear the screen
clear();
// draw the current state of the board
draw();
// saves the current state of the board (for testing)
save();
// check for win
if (won())
{
printf("ftw!\n");
break;
}
// prompt for move
printf("Tile to move: ");
int tile = GetInt();
// move if possible, else report illegality
if (!move(tile))
{
printf("\nIllegal move.\n");
usleep(500000);
}
// sleep for animation's sake
usleep(500000);
}
// that's all folks
return 0;
}
/**
* Clears screen using ANSI escape sequences.
*/
void clear(void)
{
printf("\033[2J");
printf("\033[%d;%dH", 0, 0);
}
/**
* Greets player.
*/
void greet(void)
{
clear();
printf("GAME OF FIFTEEN\n");
usleep(2000000);
}
/**
* Initializes the game's board with tiles numbered 1 through d*d - 1,
* (i.e., fills board with values but does not actually print them),
* whereby board[i][j] represents row i and column j.
*/
void init(void)
{
// TODO
//populates the board with all the numbers and the blank space being 0
for(int i=0; i<d; i++)
{
for(int j=0;j<d;j++)
{
board[i][j]= (d*d)-(i*d)-j-1;
//Swap 2 & 1 if number of tiles are even)
if( (d*d)%2 == 0 )
{
//Assign value for original value of 2 to become 1 (swapping)
board[d-1][d-3] = 1;
//Assign value for original value of 1 to become 2 (swapping)
board[d-1][d-2] = 2;
// printf(" %d ",board[i][j]);
}
}
}
}
/**
* Prints the board in its current state.
*/
void draw(void)
{
// TODO
for(int i=0;i<d;i++)
{
for(int j=0;j<d;j++)
{
if(board[i][j]>=10)
{
printf(" %d", board[i][j]);
}
if(board[i][j]<10 && board[i][j]>0)
{
printf(" %2d", board[i][j]);
}
if(board[i][j]== 0)
{
printf(" _");
}
}
printf(" \n");
}
}
/**
* If tile borders empty space, moves tile and returns true, else
* returns false.
*/
bool move(int tile)
{
// TODO
//Find the tile player entered
for(int i=0;i<d;i++)
{
for(int j=0;j<d;j++)
{
//If tile entered is valid
if(tile==board[i][j])
{
// temp value to store tile player wants to move
//check if empty is right of tile | if valid, swap
if(board[i][j+1]==0 && (j+1<d))
{
board[i][j+1]=tile;
board[i][j]=0;
return true;
}
//check if empty is left of tile | if valid, swap
if(board[i][j-1]==0&& (j-1>=0))
{
board[i][j-1]=tile;
board[i][j]=0;
return true;
}
//check if empty is top of tile | if valid, swap
if(board[i-1][j]==0 && (i-1>=0))
{
board[i-1][j]=tile;
board[i][j]=0;
return true;
}
//check if empty is bottom of tile | if valid, swap
if(board[i+1][j]==0 && (i+1<d))
{
board[i+1][j]=tile;
board[i][j]=0;
return true;
}
else
return false;
}
}
}
return false;
}
/**
* Returns true if game is won (i.e., board is in winning configuration),
* else false.
*/
bool won(void)
{
// TODO
int win[MAX][MAX];
for(int i=0;i<d;i++)
{
for(int j=0; j<d; j++)
{
win[i][j]= (i*d)+(j+1);
if(win[i][j]==d*d)
win[i][j]=0;
if(board[i][j]== win[i][j])
return 0;
}
}
return false;
}
/**
* Saves the current state of the board to disk (for testing).
*/
void save(void)
{
// log
const string log = "log.txt";
// delete existing log, if any, before first save
static bool saved = false;
if (!saved)
{
unlink(log);
saved = true;
}
// open log
FILE* p = fopen(log, "a");
if (p == NULL)
{
return;
}
// log board
fprintf(p, "{");
for (int i = 0; i < d; i++)
{
fprintf(p, "{");
for (int j = 0; j < d; j++)
{
fprintf(p, "%i", board[i][j]);
if (j < d - 1)
{
fprintf(p, ",");
}
}
fprintf(p, "}");
if (i < d - 1)
{
fprintf(p, ",");
}
}
fprintf(p, "}\n");
// close log
fclose(p);
}

Could this be a problem that board[i][j]==win[i][j] are comparing
addresses instead of the values?
No, you just got the comparison and the return value in the winning configuration wrong (1 is true, 0 is false; to not get confused, just use 1 and 0), so change in won()
if(board[i][j]== win[i][j])
to
if (board[i][j] != win[i][j])
and
return false;
to
return 1;
then it works.

Related

Can't Pass/Return Structs and Functions in C

I know it's inefficient, but I'm new at C, so I want to wrap my head around the procedure before worrying about optimizing my code. Basically I'm working on a Sudoku Solver. I have made multiple .c files for each function I intend to employ, all under the same project folder. Here's how it goes:
Setup.h - defines a nested structure. Inside the nested structure is a 9x9 array, and structures which reference each row, column, and box within that array.
typedef struct puzzle
{
int Sudoku[9][9];
int * pSudoku;
struct Rows
{
int * pRowValues[9][9];
int RowNumber[9];
} Row;
struct Columns
{
int * pColumnValues[9][9];
int ColumnNumber[9];
} Column;
struct Boxes
{
int * pBoxValues[9][9];
int BoxNumber[9];
} Box;
} Puzzle;
Setup.c - initializes the nested structure to all 0's. Creates pointers in the structure to use later.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
struct Puzzle Setup()
{
/*
*************************
First, set up the problem
*************************
*/
int NullMatrix[9][9] = {0};
int ThisIsHowCountingWorks[9] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
memcpy(Puzzle1.Sudoku, NullMatrix, sizeof(Puzzle1.Sudoku));
memcpy(Puzzle1.Row.RowNumber, ThisIsHowCountingWorks, sizeof(Puzzle1.Row.RowNumber));
memcpy(Puzzle1.Column.ColumnNumber, ThisIsHowCountingWorks, sizeof(Puzzle1.Column.ColumnNumber));
memcpy(Puzzle1.Box.BoxNumber, ThisIsHowCountingWorks, sizeof(Puzzle1.Box.BoxNumber));
Puzzle1.pSudoku = &Puzzle1.Sudoku[0][0];
/*
************************************************
Define pointers for the values and the Structure
************************************************
*/
//Rows
for(int Set=0; Set<9; Set++)
{
for(int Value=0; Value<9; Value++)
{
Puzzle1.Row.pRowValues[Value][Set] = &Puzzle1.Sudoku[Value][Set];
}
}
//Columns
for(int Set=0; Set<9; Set++)
{
for(int Value=0; Value<9; Value++)
{
Puzzle1.Column.pColumnValues[Value][Set] = &Puzzle1.Sudoku[Set][Value];
}
}
//Boxes
for(int Set=0; Set<3; Set++)
{
for(int Bump=0; Bump<3; Bump++)
{
for(int Value=0; Value<9; Value++)
{
if(Value<3)
{
Puzzle1.Box.pBoxValues[Value][Bump + 3*Set] = &Puzzle1.Sudoku[3*Bump + Value-0][0 + 3*Set];
}
else if(Value>=3&&Value<6)
{
Puzzle1.Box.pBoxValues[Value][Bump + 3*Set] = &Puzzle1.Sudoku[3*Bump + Value-3][1 + 3*Set];
}
else if(Value>=6)
{
Puzzle1.Box.pBoxValues[Value][Bump + 3*Set] = &Puzzle1.Sudoku[3*Bump + Value-6][2 + 3*Set];
}
}
}
}
return Puzzle1;
}
Input.c - asks the user for the given values, and assigns them to the correct place in the 9x9 array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
/*
********************************************
In this bit, we get some info from the user
and then assign that cleverly to the puzzle.
********************************************
*/
struct Puzzle Input(Puzzle Puzzle1)
{
printf(
"*************************************\n"
"Welcome to the Super Sudoku Solver!!!\n"
" I am your host, Puzzle Pat!\n"
"*************************************\n"
"\n"
"\n"
"\n"
"Before we begin, may I get your name?\n"
);
char name[50];
scanf("%100s", name);
printf(
"Hello, %s!\n"
"It's good to see you!\n"
"\n"
"I would like you to enter the values\n"
"given in your Sudoku puzzle.\n"
"\n"
"Please give them to me in this format:\n"
"Row Number, Column Number, Value Number\n"
"\n"
"So for example, if there's a 3 on row 2,\n"
"column 5, you'd type in '2, 5, 3'\n\n",
name
);
char spot1[8];
scanf("%10[a-z | A-Z | 0-9/,.-]", spot1[8]);
int assignment[3];
assignment[0] = (int)spot1[0]-1;
assignment[1] = (int)spot1[3]-1;
assignment[2] = (int)spot1[6];
Puzzle1.Sudoku[assignment[0]][assignment[1]] = assignment[2];
printf("Great! Are there any more entries you want to record?\n");
char more;
scanf("%10s", more);
int loop = 0;
while(more=="Yes"||more=="yes"||more=="Y"||more||"y")
{
char Support[10][15] =
{
"Cool"
"Awesome"
"Nice"
"Alright"
"Sweet"
"Great"
"Excellent"
"Wonderful"
"Heck yeah"
"Gnarly"
};
printf("\nOkay, add the next number the same way you did the last one.\n\n");
char spot2[8];
scanf("%10[a-z | A-Z | 0-9/,.-]", spot2[8]);
int assignment2[3];
assignment2[0] = (int)spot2[0]-1;
assignment2[1] = (int)spot2[3]-1;
assignment2[2] = (int)spot2[6];
Puzzle1.Sudoku[assignment[0]][assignment[1]] = assignment[2];
printf("%s! Are there any more entries you want to record?\n", Support[loop]);
scanf("%10s", more);
if(loop<9)
{
loop = loop + 1;
}
else
{
loop = 0;
}
}
return Puzzle1;
}
Calculate.c - checks each slot of the array if a 1-9 can go there. If only one number can go there, it assigns it there. If multiple can, it skips it. And it stops if nothing can go there.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
/*
****************************************
Here, we will calculate the empty blanks
****************************************
*/
struct Puzzle Calculate(Puzzle Puzzle1)
{
/*
************************************************************
First, we need to see if there are any zeroes to begin with.
************************************************************
*/
int Yes=0;
int look, here;
int count = 0;
for(look=0; look<9; look++)
{
for(here=0; here<9; here++)
{
if(Puzzle1.Sudoku[look][here] == 0)
{
Yes=1;
}
}
}
/*
***************************************************************
If there aren't, it's good to send a sassy message to the user.
***************************************************************
*/
if(Yes==0)
{
printf("You gave me an already solved Sudoku, baka!!!\n");
}
/*
******************************************************
If there are, we need to set up a loop with a counter.
******************************************************
*/
Freedom:
while(Yes==1)
{
count = count + 1;
/*
********************************************************************************
In case there aren't enough given values, we need to avoid an infinite loop. We
choose 82, because in the worst case, the Sudoku will need to be solved from the
last value to the first, and will require 81 loops if blank. This loop variable
can also be returned if we want, to see how many loops it took to solve it.
********************************************************************************
*/
if(count==82)
{
printf("Error, there are multiple possible solutions for this Sudoku,\nAnd thus it is invalid.\n");
Yes = 0;
break;
}
// This is the normal case.
else
{
/*
*****************************************************************************************
We need to start by verifying that the puzzle isn't solved already, since we are looping.
*****************************************************************************************
*/
for(look=0; look<9; look++)
{
for(here=0; here<9; here++)
{
if(Puzzle1.Sudoku[look][here] == 0) // If any value in this entire matrix is still 0, go to the calculation portion.
{
goto NotSolved;
}
else // If every value is non-zero, change Yes to 0 to nullify the while loop.
{
Yes = 0;
}
}
}
/*
************************************************************************************************
Once we have solved the Sudoku, it's time to send the victory message and break out of the loop.
************************************************************************************************
*/
if(Yes==0)
{
printf("Congratulations, we've solved the Sudoku!\n");
break;
}
/*
**********************************************************
If we haven't solved the Sudoku, it's time to get solving.
**********************************************************
*/
else
{
NotSolved:
/*
*****************************************************************
Since there are zeroes left, we need to find them and solve them.
*****************************************************************
*/
for(look=0; look<9; look++)
{
for(here=0; here<9; here++)
{
if(Puzzle1.Sudoku[look][here] == 0)
{
/*
****************************************************************************************
Since we are inside the same iteration machine as before, we are already where the 0 is.
Now we need to find what numbers it can be. If it can be one number, we need to assign
that number to that spot; if it can be multiple numbers, we need to skip that space for
now and move on; and if it can be no numbers, we have an unsolvable Sudoku.
****************************************************************************************
*/
int a=0, b=0, c=0, d=0, e=0, f=0, g=0, h=0, i=0; // Initialize number-specific variables
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 1's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==1)
{
a=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==1)
{
a=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==1)
{
a=0;
}
else
{
a=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 2's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==2)
{
b=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==2)
{
b=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==2)
{
b=0;
}
else
{
b=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 3's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==3)
{
c=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==3)
{
c=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==3)
{
c=0;
}
else
{
c=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 4's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==4)
{
d=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==4)
{
d=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==4)
{
d=0;
}
else
{
d=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 5's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==5)
{
e=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==5)
{
e=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==5)
{
e=0;
}
else
{
e=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 6's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==6)
{
f=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==6)
{
f=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==6)
{
f=0;
}
else
{
f=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 7's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==7)
{
g=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==7)
{
g=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==7)
{
g=0;
}
else
{
g=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 8's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==8)
{
h=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==8)
{
h=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==8)
{
h=0;
}
else
{
h=1;
}
}
for(int scan=0; scan<9; scan++) // Check Row-Column-Box for 9's
{
if(*(Puzzle1.Row.pRowValues[scan][here])==9)
{
i=0;
}
else if(*(Puzzle1.Column.pColumnValues[scan][here])==9)
{
i=0;
}
else if(*(Puzzle1.Box.pBoxValues[scan][here])==9)
{
i=0;
}
else
{
i=1;
}
}
if((a+b+c+d+e+f+g+h+i)<1) // If that space can't be anything, we've hit a dead end and need to break free.
{
printf("Error, this puzzle is unsolvable,\nAnd is therefore invalid");
Yes=0;
goto Freedom;
}
else if((a+b+c+d+e+f+g+h+i)==1) // If that space can be only one number, change it to that number.
{
if(a==1)
{
Puzzle1.Sudoku[look][here] = 1;
}
else if(b==1)
{
Puzzle1.Sudoku[look][here] = 2;
}
else if(c==1)
{
Puzzle1.Sudoku[look][here] = 3;
}
else if(d==1)
{
Puzzle1.Sudoku[look][here] = 4;
}
else if(e==1)
{
Puzzle1.Sudoku[look][here] = 5;
}
else if(f==1)
{
Puzzle1.Sudoku[look][here] = 6;
}
else if(g==1)
{
Puzzle1.Sudoku[look][here] = 7;
}
else if(h==1)
{
Puzzle1.Sudoku[look][here] = 8;
}
else if(i==1)
{
Puzzle1.Sudoku[look][here] = 9;
}
}
else if((a+b+c+d+e+f+g+h+i)>1) // If that space can be multiple numbers, move on. The looping should eventually solve it.
{
continue;
}
}
}
}
}
}
}
return Puzzle1;
}
main.c - calls each of these functions, and then prints the output.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "Setup.h"
struct Puzzle Setup(Puzzle);
struct Puzzle Input(Puzzle);
struct Puzzle Calculate(Puzzle);
int main()
{
/*
********************
First, run the Setup
********************
*/
Puzzle Setup();
/*
*****************************************
Then get input about this specific puzzle
*****************************************
*/
Puzzle Input(Puzzle1);
/*
********************************************
After that, run Calculate to get the answers
********************************************
*/
printf("Alright, leave the rest to me!\n\n");
Puzzle Calculate(Puzzle1);
/*
***************************
Finally, output the results
***************************
*/
printf("The solution is\n");
for(int r=0; r<9; r++)
{
if(r==3||r==6)
{
printf("---------\n");
}
for(int c=0; c<9; c++)
{
if(c==3||c==6)
{
printf("|");
}
printf("%d", Puzzle1.Sudoku[c][r]);
if(c==8)
{
printf("\n");
}
}
}
return(0);
}
Now what I'm trying to do is to #include the Setup.h, give the function prototypes, initialize the nested structure in Setup.c (takes no argument, returns the struct), then pass that struct to Input. Input changes the values in the struct and returns them to main with the new values. Main sends it to Calculate, then Calculate returns the final struct to main to be output.
Again, I know the struct is copied each time, and it's horribly inefficient, plus stupidly long, but for now it's the easiest way for me to keep track of what the program is doing. The specific error messages I'm getting repeatedly are "unknown type name", "expected declaration specifiers before 'Puzzle' ", and "return type is an incomplete type". And the vast majority of the time, it flags the first line of the Calculate.c file, "struct Puzzle Calculate(Puzzle Puzzle1){"
I added the code so that you all could see specifics, but I do apologize for how long it is... Any help would be appreciated, because I can't seem to track down the root of the problem. I've tried with and without typedef-ing it in the header file, I've tried all kinds of syntax, I've tried putting it all into one file, I've tried having the #include "Setup.h" in just one file or in all of them, and I've tried passing pointers instead of the structs themselves. So any suggestions are welcome!
I think your problem comes from your return types, for exemple struct Puzzle Setup(Puzzle);
Your structure is named struct puzzle (with a lower case "p") and Puzzle is an alias for it.
Either use the return type Puzzle or struct puzzle and it should be fine.

Pthread data race that drives me crazy

I posted a similar question to this one a few weeks ago where I had trouble finding the data race in my N-queens program using pthreads in C. Why is my multithreaded C program not working on macOS, but completely fine on Linux?
I got a few suggestions in the comments sections of the post and I really tried my best to make corrections based on them. I sat with the suggestions a few days, changed some parts but the data race persisted and I just cannot understand why. There are counters inside critical sections for the number of productions and consumptions. I feel completely blind when looking through the code and analyzing it, I'm aware that consumptions are too many but the synchronization around that code fragment should with my knowledge be correct, but obviously something's not right. External input would be greatly appreciated.
This is the code I'm using and I'm not sure how to reduce its size to still reproduce the issue. I compile it with gcc (clang-1205.0.22.11) on macOS Monterey (12.1) using a MacBook Pro 2020 x86_64 architecture.
compile: gcc -o 8q 8q.c*
run: ./8q <consumers> <N>, NxN chess board, N queens to place
parameters: ./8q 2 4 Enough to highlight the problem (should yield 2 solutions, but every other run yields 3+ solutions, i.e duplicate solutions exist
note: running the program with ./8q 2 4 should give 2 solutions, 1820 productions and 1820 consumptions.
#ifndef _REENTRANT
#define _REENTRANT
#endif
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
typedef struct stack_buf {
int positions[8];
int top;
} stack_buf;
typedef struct global_buf {
int positions[8];
int buf_empty;
long prod_done;
int last_done;
} global_buf;
typedef struct print_buf {
int qpositions[100][8];
int top;
} print_buf;
stack_buf queen_comb = { {0}, 0 };
print_buf printouts = { {{0}}, 0 };
global_buf global = { {0}, 1, 0, 0 };
int N; //NxN board and N queens to place
long productions = 0;
long consumptions = 0;
pthread_mutex_t buffer_mutex, print_mutex;
pthread_cond_t empty, filled;
/* ##########################################################################################
################################## VALIDATION FUNCTIONS ##################################
########################################################################################## */
/* Validate that no queens are placed on the same row */
int valid_rows(int qpositions[]) {
int rows[N];
memset(rows, 0, N*sizeof(int));
int row;
for (int i = 0; i < N; i++) {
row = qpositions[i] / N;
if (rows[row] == 0) rows[row] = 1;
else return 0;
}
return 1;
}
/* Validate that no queens are placed in the same column */
int valid_columns(int qpositions[]) {
int columns[N];
memset(columns, 0, N*sizeof(int));
int column;
for (int i = 0; i < N; i++) {
column = qpositions[i] % N;
if (columns[column] == 0) columns[column] = 1;
else return 0;
}
return 1;
}
/* Validate that left and right diagonals aren't used by another queen */
int valid_diagonals(int qpositions[]) {
int left_bottom_diagonals[N];
int right_bottom_diagonals[N];
int row, col, temp_col, temp_row, fill_value, index;
for (int queen = 0; queen < N; queen++) {
row = qpositions[queen] / N;
col = qpositions[queen] % N;
/* position --> left down diagonal endpoint (index) */
fill_value = col < row ? col : row; // closest to bottom or left wall
temp_row = row - fill_value;
temp_col = col - fill_value;
index = temp_row * N + temp_col; // board position
for (int i = 0; i < queen; i++) { // check if interference occurs
if (left_bottom_diagonals[i] == index) return 0;
}
left_bottom_diagonals[queen] = index; // no interference
/* position --> right down diagonal endpoint (index) */
fill_value = (N-1) - col < row ? N - col - 1 : row; // closest to bottom or right wall
temp_row = row - fill_value;
temp_col = col + fill_value;
index = temp_row * N + temp_col; // board position
for (int i = 0; i < queen; i++) { // check if interference occurs
if (right_bottom_diagonals[i] == index) return 0;
}
right_bottom_diagonals[queen] = index; // no interference
}
return 1;
}
/* ##########################################################################################
#################################### HELPER FUNCTION(S) ####################################
########################################################################################## */
/* print the collected solutions */
void print(print_buf printouts) {
static int solution_number = 1;
int placement;
pthread_mutex_lock(&print_mutex);
for (int sol = 0; sol < printouts.top; sol++) { // all solutions
printf("Solution %d: [ ", solution_number++);
for (int pos = 0; pos < N; pos++) {
printf("%d ", printouts.qpositions[sol][pos]+1);
}
printf("]\n");
printf("Placement:\n");
for (int i = 1; i <= N; i++) { // rows
printf("[ ");
placement = printouts.qpositions[sol][N-i];
for (int j = (N-i)*N; j < (N-i)*N+N; j++) { // physical position
if (j == placement) {
printf(" Q ");
} else printf("%2d ", j+1);
}
printf("]\n");
}
printf("\n");
}
pthread_mutex_unlock(&print_mutex);
}
/* ##########################################################################################
#################################### THREAD FUNCTIONS ####################################
########################################################################################## */
/* entry point for each worker (consumer) workers will
check each queen's row, column and diagonal to evaluate
satisfactory placements */
void *eval_positioning(void *id) {
long thr_id = (long)id;
int qpositions[N]; // on stack (thread-private)
while (1) {
pthread_mutex_lock(&buffer_mutex);
while (global.buf_empty == 1) { // no element
if (global.last_done) { // last done, no combinations left
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_signal(&filled);
return NULL;
}
if (global.prod_done) {
global.last_done = 1;
break;
}
pthread_cond_wait(&filled, &buffer_mutex);
}
memcpy(qpositions, global.positions, N*sizeof(int)); // copy to local scope
global.buf_empty = 1;
consumptions++;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_signal(&empty);
if (valid_rows(qpositions) && valid_columns(qpositions) && valid_diagonals(qpositions)) {
pthread_mutex_lock(&print_mutex);
memcpy(printouts.qpositions[printouts.top], qpositions, N*sizeof(int)); /* save for printing later */
printouts.top++;
pthread_mutex_unlock(&print_mutex);
}
}
return NULL;
}
/* recursively generate all possible queen_combs */
void rec_positions(int pos, int queens) {
if (queens == 0) { // base case
pthread_mutex_lock(&buffer_mutex);
while (global.buf_empty == 0) { // while production hasn't been consumed
pthread_cond_wait(&empty, &buffer_mutex);
}
memcpy(global.positions, queen_comb.positions, N*sizeof(int));
productions++;
global.buf_empty = 0;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_signal(&filled);
return;
}
for (int i = pos; i <= N*N - queens; i++) {
queen_comb.positions[queen_comb.top++] = i;
rec_positions(i+1, queens-1);
queen_comb.top--;
}
}
/* binomial coefficient | without order, without replacement
8 queens on 8x8 board: 4'426'165'368 queen combinations */
void *generate_positions(void *arg) {
rec_positions(0, N);
pthread_mutex_lock(&buffer_mutex);
global.prod_done = 1;
pthread_mutex_unlock(&buffer_mutex);
pthread_cond_broadcast(&filled); //wake all to
return NULL;
}
/* ##########################################################################################
########################################## MAIN ##########################################
########################################################################################## */
/* main procedure of the program */
int main(int argc, char *argv[]) {
if (argc < 3) {
printf("usage: ./8q <workers> <board width/height>\n");
exit(1);
}
int workers = atoi(argv[1]);
N = atoi(argv[2]);
if (N < 2 || N > 8) {
printf("Wrong input! 2 <= N <= 8\n");
return 0;
}
struct timeval start, stop;
double elapsed;
pthread_t consumers[workers];
pthread_t producer;
printf("\n");
gettimeofday(&start, NULL);
pthread_create(&producer, NULL, generate_positions, NULL);
for (long i = 0; i < workers; i++) {
pthread_create(&consumers[i], NULL, eval_positioning, (void*)i+1);
}
pthread_join(producer, NULL);
for (int i = 0; i < workers; i++) {
pthread_join(consumers[i], NULL);
char id[2];
sprintf(id, "%d", i+1);
write(1, id, strlen(id));
write(1, " done\n\n", 6);
}
gettimeofday(&stop, NULL);
elapsed = stop.tv_sec - start.tv_sec;
elapsed += (stop.tv_usec - start.tv_usec) / (double)1000000;
/* go through all valid solutions and print */
print(printouts);
printf("board: %dx%d, workers: %d (+1), exec time: %fs, solutions: %d\n", N, N, workers, elapsed, printouts.top);
printf("productions: %ld\nconsumptions: %ld\n", productions, consumptions);
return 0;
}
You're not initializing your mutexes and condition variables. The result is UB when used in pthread APIs. Two ways to do this, the simplest is just use the proper initializer:
pthread_mutex_t buffer_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t print_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t empty = PTHREAD_COND_INITIALIZER;
pthread_cond_t filled = PTHREAD_COND_INITIALIZER;
Unrelated, but worth mentioning, the last_done ideology is not necessary. This can be done with just the buf_empty and prod_done states. Specifically:
void *eval_positioning(void *tid)
{
int qpositions[N]; // on stack (thread-private)
while (1)
{
pthread_mutex_lock(&buffer_mutex);
// while still producing *and* the buffer is empty
while (!global.prod_done && global.buf_empty)
pthread_cond_wait(&filled, &buffer_mutex);
// if both are true, we're done. nothing to process, and
// there never will be (e.g. prod_done)
if (global.prod_done && global.buf_empty)
{
// signal anyone else waiting on that mutex+cvar
pthread_cond_signal(&filled);
break;
}
// if we have a buffer to process (even if prod_done is true)
else if (!global.buf_empty)
{
// make local copy of buffer
memcpy(qpositions, global.positions, sizeof qpositions);
++consumptions;
// mark global buffer as ready-to-receive
global.buf_empty = 1;
pthread_cond_signal(&empty);
pthread_mutex_unlock(&buffer_mutex);
// if validated...
if (valid_rows(qpositions) && valid_columns(qpositions) && valid_diagonals(qpositions))
{
// record and bump the printout counter.
pthread_mutex_lock(&print_mutex);
int row = printouts.top++;
pthread_mutex_unlock(&print_mutex);
// this need not be protected by the mutex. we "own"
// this now, and can just blast away.
memcpy(printouts.qpositions[row], qpositions, sizeof qpositions);
}
}
else
{
pthread_mutex_unlock(&buffer_mutex);
}
}
// make sure we unlock this
pthread_mutex_unlock(&buffer_mutex);
return tid;
}
With proper initialization of the concurrency materials, and the above eval processor, this is the consistent output:
Output
1 done
2 done
Solution 1: [ 2 8 9 15 ]
Placement:
[ 13 14 Q 16 ]
[ Q 10 11 12 ]
[ 5 6 7 Q ]
[ 1 Q 3 4 ]
Solution 2: [ 3 5 12 14 ]
Placement:
[ 13 Q 15 16 ]
[ 9 10 11 Q ]
[ Q 6 7 8 ]
[ 1 2 Q 4 ]
board: 4x4, workers: 2 (+1), exec time: 0.013001s, solutions: 2
productions: 1820
consumptions: 1820
Apologies for the puny laptop performance numbers

c program to check valid sudoku

i'm writing c code to check whether given matrix is valid sudoku solution or not.
Input would be matrix of n*n size.
I have written code to check row and column but i'm not getting how to validate grids of sqrt(n)*sqrt(n) size.
my code is here
#include<stdio.h>
int main()
{
int i,j,count=0,sumrow;
int sumcol;
int n;
scanf("%d",&n);
int arr[n+1][n+1];
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&arr[i][j]);
for(i=1;i<=n;i++)
{
sumcol=0;
for(j=1;j<=n;j++)
sumcol+=arr[j][i];
if(sumcol!=(n*(n+1)/2))
count++;
}
for(i=1;i<=n;i++)
{
sumrow=0;
for(j=1;j<=n;j++)
{
sumrow+=arr[i][j];
}
// printf("%d\n",sumrow);
if(sumrow!=(n*(n+1)/2))
count++;
}
//printf("count%d ",count);
if(count==0)
printf("yes");
else
printf("no");
return 0;
}
Here i have a better solution. Instead of sum, we can use an integer flag.
//read sudoku
for(i=0;i<9;i++)
for(j=0;j<9;j++)
{
scanf("%c",&c);
a[i][j]=c-'0';
}
//checking rows
for(i=0;i<9;i++)
{
flag=0x0000;
for(j=0;j<9;j++)
flag|=1<<(a[i][j]-1);
if(flag!=0x01FF)
report("row",i,j-1);
}
//checking cols
for(j=0;j<9;j++)
{
flag=0x0000;
for(i=0;i<9;i++)
flag|=1<<(a[i][j]-1);
if(flag!=0x01FF)
report("col",i-1,j);
}
//checking Squares (3x3)
for(si=0;si<3;si++)
{
for(sj=0;sj<3;sj++)
{
flag=0x0000;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
flag|=1<<(a[si*3+i][sj*3+j]-1);
}
if(flag!=0x01FF)
report("square",si*3+i-1,sj*3+j-1);
}
}
printf("\nThe sudoku is correct");
For detailed description, You may visit this link
You can check each of the smaller squares whether they are valid or not.For example if n=9 you have to check each of the 3 by 3 squares.To check each smaller square you can use an array of 10 elements and check whether any of the 1 to 9 value is repeated or not.
The algorithm is as follows
for each of the smaller grids
if(any of the digit repeats in a smaller grid)
return 0;
return 1;//valid
Following is some code to do the same
//A is the grid
int small=sqrt(n);
for(int i=0;i<small;i++)
{
for(int j=0;j<small;j++)
{
int row=small*i;//this will find the corresponding row
int col=small*j;//this will find the corresponding column
vector<int> used(10,0)
for(int p=row; p<row+small; p++) {
for(int q=col; q<col+small; q++)
{
if(A[p][q]=='0')//0 is not valid
return 0;
if(used[A[p][q]-'0']==1)//this digit has already been used
return 0;
if(used[A[p][q]-'0']) return 0;
used[A[p][q]-'0']=1;//now this particular digit has occurred and should not occur again
}
}
}
}
//if all's well return 1
return 1;
Note that the above code assumes that entire grid is filled and is not empty.If you want to check a partially filled grid,introduce a check.
int main() {
int a[10][10],i,j,n,k,sum,sum1,sum2,sum3,x,l;
printf("enter the size N of N*N sudoku\n");
scanf("%d",&n);
printf("enter the entries of sudoku row wise \n");
for (i=1;i<=n;i++) {
for (j=1;j<=n;j++) {
scanf("%d",&a[i][j]);
}
printf("\n");
}
printf("---------------------------------\n\n\n\n");
printf("the matrix you entered is \n");
for (i=1;i<=n;i++) {
for (j=1;j<=n;j++) {
printf("%d",a[i][j]);
printf("|");
}
printf("\n");
}
for (i=1;i<=n;i++) {
for (k=i;k==i;k++) {
sum=0;
for (j=1;j<=n;j++) {
sum = sum + a[i][j];
}
if(sum!=45)
x=1;
}
}
for (j=1;j<=n;j++) {
for(k=j;k==j;k++) {
sum=0;
for (i=1;i<=n;i++) {
sum = sum+a[i][j];
}
if (sum!=45)
x=1;
}
}
for (k=1;k<=3;k++) {
l = (1+(k-1)*n/3);
for (i=l;i<=k*n/3;i++) {
for(j=1;j<=3;j++) {
sum1 = sum1+a[i][j];
}
for (j=4;j<=6;j++) {
sum2 = sum2+a[i][j];
}
for (j=7;j<=9;j++) {
sum3 = sum3+a[i][j];
}
}
if (sum1!=45||sum2!=45||sum3!=45)
x=1;
}
if (x==1)
printf("sudoku not correct \n");
else
printf("correct sudoku");
return 0;
}
bool validateMatrix(int g_iMatrix1[][MAXCOLS],
int iROWS,
int iCOLS)
{
bool bRowUsed[MAXROWS][MAXCOLS] = {0};
bool bColUsed[MAXROWS][MAXCOLS] = {0};
bool bBlockUsed[MAXROWS][MAXCOLS] = {0};
//Matrix to keep record if current value is already set in current row..
memset(bRowUsed, false, (MAXROWS) * (MAXCOLS));
//Matrix to keep record if current value is already set in current column..
memset(bColUsed, false, (MAXCOLS) * (MAXCOLS));
//Matrix to keep record if current value is already set in current block of iSQRT * iSQRT..
//Lets assume the matrix is of size 9 * 9..
//So there will be 9 block of 3 * 3..
//Number the blocks from left to right as 0 to 8..
//We will be mapping 0 the block to 0th row, 1st block to 1st row, 2nd block to 2nd row and so on..
memset(bBlockUsed, false, (MAXROWS) * (MAXCOLS));
int iRows = 0,iCols = 0;
int iSQRT = int(sqrt(MAXCOLS));
for(iRows = 0;iRows < iROWS;iRows++)
{
for(iCols = 0;iCols < iCOLS;iCols++)
{
if(bRowUsed[iRows][g_iMatrix1[iRows][iCols] - 1] == true)
{
return false;
}
if(bColUsed[g_iMatrix1[iRows][iCols] - 1][iCols] == true)
{
return false;
}
//Number the blocks from left to right as 1 to 9..
//We will be mapping 0 the block to 0th row, 1st block to 1st row, 2nd block to 2nd row and so on..
//((iRows / iSQRT) * iSQRT) + (iCols / iSQRT) will map the block with above logic..
if(bBlockUsed[((iRows / iSQRT) * iSQRT) + (iCols / iSQRT)][g_iMatrix1[iRows][iCols] - 1] == true)
{
return false;
}
bRowUsed[iRows][g_iMatrix1[iRows][iCols] - 1] = true;
bColUsed[g_iMatrix1[iRows][iCols] - 1][iCols] = true;
bBlockUsed[((iRows / iSQRT) * iSQRT) + (iCols / iSQRT)][g_iMatrix1[iRows][iCols] - 1] = true;
}
}
return true;
}

Input line freezing, segmentation fault

I'm working on a project for a class and have been stuck for quite a while. When I unit tested the input earlier, it accepted the values for numOfDataSets and createDataSets without error. Now, however, after typing in any set of values for createDataSets, the code freezes after the first input until I enter any character (such as 1 or a), then errors with a segmentation fault. I am not sure what went wrong, and I would appreciate any help.
#include <stdio.h>
#include <stdlib.h>
// Function to return the number of data sets the user wants.
int numOfDataSets(void) {
int ret;
printf("Enter number of data sets: ");
scanf("%d", &ret);
return ret;
}
// Function that creates the data sets in the input arrays.
void createDataSets(float **inputArr, int inputLength, int *lengths) {
int i = 0, j, k;
float value, *currentSet;
// For every element in inputArr...
while (i < inputLength) {
printf("Enter the number of values in this data set, followed by the values: ");
scanf("%d", &j);
*(lengths + i) = j;
currentSet = (float*)calloc(j, sizeof(float));
k = 0;
while (k < j-1) {
scanf("%f", &value);
*(currentSet + k) = value;
k++;
}
scanf("%f", &value);
*(currentSet + j - 1) = value;
*(inputArr + i) = (float*)&currentSet;
i++;
}
}
// Function to get int value of data set to choose.
int chooseDataSet(void) {
int ret;
printf("Enter the number of the data set on which you wish to do calculations: ");
scanf("%d", &ret);
ret = ret - 1;
return ret;
}
// Gets the number option of the operation that the user wants to do.
int getOption(void) {
int ret;
printf("Enter one of the following numbers:\n");
printf("1. Find the minimum value.\n");
printf("2. Find the maximum value.\n");
printf("3. Calculate the sum of all the values.\n");
printf("4. Calculate the average of all the values.\n");
printf("5. Sort the values in ascending order (i.e., from smallest to largest).\n");
printf("6. Select a different data set.\n");
printf("7. Exit the program.\n");
scanf("%d", &ret);
return ret;
}
// Function to find the minimum value of a dataset.
void minimum(float *ptr, int length) {
int i = 1;
float min;
min = *(ptr);
while (i < length) {
if (*(ptr + i) < min) {
min = *(ptr + i);
}
i++;
}
printf("The minimum value of the set is: %d\n", min);
}
// Function to find the maximum value of a dataset.
void maximum(float *ptr, int length) {
int i = 1;
float max;
max = *(ptr);
while (i < length) {
if (*(ptr + i) > max) {
max = *(ptr + i);
}
i++;
}
printf("The maximum value of the set is: %d\n", max);
}
// Function to find the sum of the values of a dataset.
void sum(float *ptr, int length) {
int i = 1;
float sum;
sum = *(ptr);
while (i < length) {
sum = sum + *(ptr + i);
i++;
}
printf("The sum of the set is: %d\n", sum);
}
// Function to find the average of the values of a dataset.
void average(float *ptr, int length) {
int i = 1;
float sum;
sum = *(ptr);
while (i < length) {
sum = sum + *(ptr + i);
i++;
}
sum = sum / length;
printf("The average of the set is: %d\n", sum);
}
// Function to sort the values of a dataset.
void sort(float *ptr, int length) {
int i = 1, j;
float temp;
while (i < length) {
j = i;
while ((j > 0) && (*(ptr + j - 1) > *(ptr + j))) {
temp = *(ptr + j);
*(ptr + j) = *(ptr + j - 1);
*(ptr + j - 1) = temp;
j--;
}
i++;
}
printf("The sorted array is: ");
i = 0;
while (i < length) {
printf("%f\t", *(ptr + i));
i++;
}
printf("\n");
}
// Main method...
int main(void) {
int *lengths, outerLength, userChoiceSet = 0, userChoiceOption = 0, breakOutterLoop = 0;
float **outer;
outerLength = numOfDataSets();
outer = (float**)calloc(outerLength, sizeof(float*));
lengths = (int*)calloc(outerLength, sizeof(int));
createDataSets(outer, outerLength, lengths);
while (breakOutterLoop == 0) {
userChoiceSet = chooseDataSet();
while ((userChoiceOption != 6) || (userChoiceOption != 7)) {
userChoiceOption = getOption();
switch (userChoiceOption)
{
case 1:
minimum(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 2:
maximum(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 3:
sum(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 4:
average(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 5:
sort(*(outer + userChoiceSet), *(lengths + userChoiceSet));
break;
case 7:
breakOutterLoop = 1;
default:
break;
}
}
}
return (0);
}
The type of input to expect from the user would be something like:
2
3 1.2 2.3 3.4
4 4.5 5.6 6.7 7.8
Your main problem is this, in createDataSets():
*(inputArr + i) = (float*)&currentSet;
What this actually does is assign the address of currentSet to each element of inputArr. This address doesn't change on each iteration, so each element of inputArr gets set to the exact same value. Moreover, this address refers to a variable local to createDataSets() which will be destroyed when that function returns, so the address will be invalid. All the arrays you're dynamically creating are just being discarded, because you're not storing the addresses.
What you should have is:
inputArr[i] = currentSet;
As you mention in the comments, your compiler warned you about this, because what you were doing was trying to store a float ** in a float *, which is rarely a good idea. By adding the cast you silenced the warning, but you didn't fix the problem it was warning you about. The number of occasions in C where a cast is actually what you want to do are relatively few. None of the casts in your program are either necessary, or wise.
A few other points...
You use the wrong format specifier in many of your printf() calls. The %d here:
printf("The minimum value of the set is: %d\n", min);
for instance, should be an %f, because min is a float.
You are overusing pointer notation which makes your code very difficult to follow. That includes very difficult for you, too. For instance, your minimum() function could be much better written as so:
void minimum(float *ptr, int length) {
float min = ptr[0];
for ( int i = 0; i < length; ++i ) {
if ( ptr[i] < min ) {
min = ptr[i];
}
}
printf("The minimum value of the set is: %f\n", min);
}
Similarly, in your switch statement, something like:
average(*(outer + userChoiceSet), *(lengths + userChoiceSet));
is much more clearly written as:
average(outer[userChoiceSet], lengths[userChoiceSet]);
You are missing a call to fflush(stdout) in a few places, where you prompt for input but do not end the prompt with an '\n'. When I ran this code on my system, the prompt did not show before it sat to wait for the input. Interactive output is line-buffered by default, in C, and if you want things to be predictable, then you need to output a '\n' or call fflush(stdout) when output needs to be displayed.
You would benefit from defining your variables closer to the time of use. Restricting the scope of your variables to the minimum feasible is generally good. For instance, in your main() function, your variable userChoiceSet is never used outside of the outer while loop, so define it inside with:
while (breakOutterLoop == 0) {
int userChoiceSet = chooseDataSet();
You don't check the return from calloc() anywhere - you must do this, because the allocation might fail. malloc() and friends return NULL on failure. There's also no real point using calloc(), here - malloc() would be more normal.
You seem to use while loops in places where for loops would be much more natural.
You haven't done too bad a job with this one, but you'll find writing larger programs easier if you make each function do just one thing. For instance, your minimum() function should just calculate the minimum, but right now it calculates it and prints it. Particularly when it comes to dealing with input in the wrong format (see point 9 below) wrapping this up in a separate function will make the functions that use that input much less cluttered, and it's easy to get a function correct and to visually debug it if it's not doing a bunch of different things at once. Also, your opportunity for reusing code goes up when you do this (e.g. right now you couldn't use that minimum() function at any place where you wanted to calculate the minimum without also printing it).
Overall, having one array for your values, and a second for their lengths, is not a good approach. Far better would be to have an array of structs, each struct having a member for the array, and a member for the length, so the two related pieces of data are packaged together.
Also, your use of scanf() is potentially troublesome. If you enter input that's not expected, your program will not fail gracefully. For instance, if you enter anything other than a number in your main menu, then you'll go into an infinite loop. Generally better is to use fgets() to read in an entire line, and use sscanf() to parse its contents. At a minimum, you should check the return from scanf() to see if it successfully read a value, and if it did not, take appropriate remedial action (like reading all the characters in the input buffer and going back to ask for more input).
Overall, bearing all of the above in mind except for the last two points, your createDataSets() function would be better looking something like this:
void createDataSets(float **inputArr, const int inputLength, int *lengths) {
for ( int i = 0; i < inputLength; ++i ) {
printf("Enter the number of values in this data set, "
"followed by the values: ");
fflush(stdout);
scanf("%d", &lengths[i]);
float * currentSet = malloc(lengths[i] * sizeof *currentSet);
if ( !currentSet ) {
perror("Couldn't allocate memory in createDataSets()");
exit(EXIT_FAILURE);
}
for ( int j = 0; j < lengths[i]; ++j ) {
scanf("%f", &currentSet[j]);
}
inputArr[i] = currentSet;
}
}
Much easier to debug, easier to follow, and easier to not get wrong in the first place.
Since I've got a bit of time on my hands, here's how I'd figure it:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
/* Maximum length of input buffer */
#define MAX_LINE 1024
/* Dataset structure */
struct dataset {
float * data;
size_t length;
};
/* Gets a single integer from user */
int getInteger(const char * prompt)
{
int value;
bool first_try = true;
char buffer[MAX_LINE];
do {
printf("%s%s: ", first_try ? "" : "Try again - ", prompt);
fflush(stdout);
fgets(buffer, MAX_LINE, stdin);
first_try = false;
} while ( sscanf(buffer, "%d", &value) != 1 );
return value;
}
/* Gets a bounded integer from user */
int getBoundedInteger(const char * prompt, const int min, const int max)
{
bool bad_input;
int value;
do {
bad_input = false;
value = getInteger(prompt);
if ( value < min ) {
printf("Too low, try again - ");
bad_input = true;
}
else if ( value > max ) {
printf("Too high, try again - ");
bad_input = true;
}
} while ( bad_input );
return value;
}
/* Gets a list of floats from user - caller must free */
float * getFloats(const char * prompt, const int num)
{
float * values = malloc(num * sizeof *values);
if ( !values ) {
perror("Couldn't allocate memory in getFloats()");
exit(EXIT_FAILURE);
}
bool bad_input = false;
do {
printf("%s%s: ", bad_input ? "Try again - " : "", prompt);
fflush(stdout);
char buffer[MAX_LINE];
fgets(buffer, MAX_LINE, stdin);
char * ptr = buffer;
int num_read = 0;
bad_input = false;
while ( *ptr && num_read < num ) {
/* Skip leading whitespace */
while ( *ptr && isspace(*ptr) ) {
++ptr;
}
/* Get and check input */
char * endptr;
float val = strtof(ptr, &endptr);
if ( ptr == endptr ) {
bad_input = true;
break;
}
/* Advance ptr and store input if good */
ptr = endptr;
values[num_read++] = val;
}
if ( num_read < num ) {
bad_input = true;
}
} while ( bad_input );
return values;
}
/* Returns the number of data sets the user wants. */
int numOfDataSets(void)
{
return getInteger("Enter number of data sets");
}
/* Creates the data sets */
void createDataSets(struct dataset ** sets, const int set_length)
{
for ( int i = 0; i < set_length; ++i ) {
struct dataset * new_set = malloc(sizeof *new_set);
if ( !new_set ) {
perror("Couldn't allocate memory for dataset");
exit(EXIT_FAILURE);
}
new_set->length = getInteger("Enter number of values in set");
new_set->data = getFloats("Enter values", new_set->length);
sets[i] = new_set;
}
}
/* Gets the number of data set to choose */
int chooseDataSet(const int min, const int max)
{
return getBoundedInteger("Choose data set", min, max) - 1;
}
/* Gets a menu choice from the user */
int getOption(void)
{
printf("Enter one of the following numbers:\n");
printf("1. Find the minimum value\n");
printf("2. Find the maximum value\n");
printf("3. Calculate the sum of all the values\n");
printf("4. Calculate the average of all the values\n");
printf("5. Sort the values in ascending order\n");
printf("6. Output the data set\n");
printf("7. Select a different data set\n");
printf("8. Exit the program\n");
return getInteger("Choose option");
}
/* Returns the minimum value in a data set */
float minimum(const struct dataset * set)
{
float min = set->data[0];
for ( size_t i = 0; i < set->length; ++i ) {
if ( set->data[i] < min ) {
min = set->data[i];
}
}
return min;
}
/* Returns the maximum value in a data set */
float maximum(const struct dataset * set)
{
float max = set->data[0];
for ( size_t i = 0; i < set->length; ++i ) {
if ( set->data[i] > max ) {
max = set->data[i];
}
}
return max;
}
/* Returns the sum of the data in a dataset */
float sum(const struct dataset * set)
{
float sum = 0;
for ( size_t i = 0; i < set->length; ++i) {
sum += set->data[i];
}
return sum;
}
/* Returns the arithmetic average of the data in a dataset */
float average(const struct dataset * set)
{
float sum = 0;
for ( size_t i = 0; i < set->length; ++i ) {
sum += set->data[i];
}
return set->length > 0 ? sum / set->length : sum;
}
/* Sorts the elements of a dataset in place */
void sort(struct dataset * set)
{
for ( size_t i = 0; i < set->length; ++i ) {
for ( size_t j = i; j && set->data[j-1] > set->data[j]; --j ) {
float temp = set->data[j];
set->data[j] = set->data[j-1];
set->data[j-1] = temp;
}
}
}
/* Prints a dataset */
void print_set(const struct dataset * set) {
for ( size_t i = 0; i < set->length; ++i ) {
printf("%.4f ", set->data[i]);
}
putchar('\n');
}
/* Main function */
int main(void)
{
/* Get and initialize sets */
const int num_sets = numOfDataSets();
struct dataset ** sets = malloc(num_sets * sizeof *sets);
if ( !sets ) {
perror("Couldn't allocate memory for sets");
return EXIT_FAILURE;
}
createDataSets(sets, num_sets);
/* Main menu */
int chosen_set = chooseDataSet(1, num_sets);
bool keep_going = true;
while ( keep_going ) {
switch ( getOption() )
{
case 1:
printf("Minimum value is %f\n\n",
minimum(sets[chosen_set]));
break;
case 2:
printf("Maximum value is %f\n\n",
maximum(sets[chosen_set]));
break;
case 3:
printf("Sum of values is %f\n\n",
sum(sets[chosen_set]));
break;
case 4:
printf("Average of values is %f\n\n",
average(sets[chosen_set]));
break;
case 5:
sort(sets[chosen_set]);
break;
case 6:
print_set(sets[chosen_set]);
break;
case 7:
chosen_set = chooseDataSet(1, num_sets);
break;
case 8:
keep_going = false;
break;
default:
break;
}
}
/* Free memory for sets */
for ( int i = 0; i < num_sets; ++i ) {
free(sets[i]->data);
free(sets[i]);
}
free(sets);
return 0;
}

Find number of paths in a 2d binary array (C)

I have been asked this question during an interview, and have been struggling to find an elegant solution (in C), Problem statement:
You are given a two-dimensional array with M rows and N columns.
You are initially positioned at (0,0) which is the top-left cell in
the array.
You are allowed to move either right or downwards.
The array is filled with 1′s and 0′s. A 1 indicates that you can move
through that cell, a 0 indicates that you cannot move through the
cell.
Write a function in C ‘numberOfPaths’ which takes in the above two dimensional array, return the number of valid paths from the top-left cell to the bottom-right cell (i.e. [0,0] to [M-1,N-1]).
Edit: forgot to mention that the requirement is for a recursive solution
help would be greatly appreciated!
Thanks
If you are looking for a recursive solution you can use DFS.
DFS (array, x, y)
{
if (array [x][y]==0 || x>M || y>N){
return;
}
if (x==M && y==N){
count++;
return;
}
DFS (array, x, y+1);
DFS (array, x+1, y);
}
The number of paths to a given point is just the number of paths to the point above, plus the number of paths to the point to the left. So, the pseudo-code would roughly be:
num_paths[0][0] = 1;
for (x = 0; x < M; ++x)
for (y = 0; y < N; ++y)
if (!allowed_through[x][y])
num_paths[x][y] = 0;
else
num_paths[x][y] = num_paths[x-1][y] + num_paths[x][y-1];
You need special cases for x=0 and y=0, but otherwise, I think that should do.
#include <stdio.h>
int count=0;
int maxrows = 10;
int maxcols = 10;
int M, N;
void DFS (int array[][10], int x, int y)
{
int r, c;
/* process element at input row and column */
if (array [x][y]==0 || x>M || y>N){
/* no path forward; return */
return;
}
if (x==M-1 && y==N-1){
/* found path; increment count */
count++;
return;
}
/* recurse: to matrix starting from same row, next column */
r = x;
c = y +1;
if (c < N-1) {
DFS (array, r,c);
} else {
/* if last column - check to see */
/* if rest of rows in last column allow for a path */
int tr = r;
while ( tr <= M-1) {
if (array[tr][c] == 1) {
tr++;
}
else {
return;
}
}
/* reached last node - path exists! */
count++;
}
/* recurse: to matrix starting from next row, same column */
r = x+1;
c = y;
if (r < M-1) {
DFS (array, r,c);
} else {
/* if last row - check to see */
/* if rest of columns in last row allow for a path */
int tc = c;
while ( tc <= N-1) {
if (array[r][tc] == 1) {
tc++;
} else {
return;
}
}
/* reached last node - path exists! */
count++;
}
}
int main () {
int i, j;
scanf("%d %d",&M,&N);
int a[10][10] = {};
int row, col;
for(i=0;i<M;i++)
for(j=0;j<N;j++)
scanf("%d", &a[i][j]);
if ((M > maxrows) || (N > maxcols)) {
printf("max of 10 rows and 10 cols allowed for input\n");
return (-1);
};
/* print input matrix */
for(row=0;row<M;row++) {
for(col=0;col<N;col++){
printf("%d ",a[row][col]);
}
printf(" EOR\n");
}
DFS(a,0,0);
printf("number of paths is %d\n", count);
return 0;
}
Try this function its a preliminary step before printing all the paths.
If the size of the vector Out is 0 then the # of paths are 0, but if size(Out) > 0 then the size of vector Nodes + 1 are the total number of paths from top left to bottom right.
#include <iostream>
#include <vector>
using namespace std;
typedef vector<pair<int,int> > vPii;
bool pathTL2BR( int Arr2D[][4], vPii &Out, vPii &Nodes,
int _x,int _y, int _M, int _N)
{
bool out1 = false;
bool out2 = false;
if( Arr2D[_x][_y] == 1 )
{
if( _y+1 < _N )
out1 = pathTL2BR( Arr2D, Out, Nodes, _x, _y+1, _M, _N);
if( _x+1 < _M )
out2 = pathTL2BR( Arr2D, Out, Nodes, _x+1, _y, _M, _N);
if( (out1 || out2) ||
( (_x == (_M-1)) && (_y == (_N-1)) ) )
{
if(out1 && out2)
Nodes.push_back( make_pair(_x,_y ) );
Out.push_back( make_pair(_x,_y ) );
return true;
}
else
return false;
}
else
return false;
}
// Driver program to test above function
int main()
{
int Arr2D[][4] = {
{1,1,1,1},
{0,1,0,1},
{0,1,0,1},
{0,1,0,1}
};
vPii Out;
vPii Nodes;
vector<vPii> Output;
pathTL2BR( Arr2D, Out, Nodes, 0, 0, 4, 4);
return 0;
}
This is a python solution, I have put explanations in the comments.
def find_num_paths(arr_2D, i, j):
# i,j is the start point and you have to travel all the way back to 0,0
if i == j and i == 0:
return 1 # you have reached the start point
if i < 0 or j < 0 or arr_2D[i][j] == 0: # out of range or no path from that point
return 0
if arr_2D[i][j] == 1:
return find_num_paths(arr_2D, i, j-1) + find_num_paths(arr_2D, i-1, j) + find_num_paths(arr_2D, i-1, j-1) # you could go one step above, to the left or diagonally up.

Resources