Logic check not outputting as expected. (Sudoku checker) C - c

I have a function that checks all the rows of a sudoku board and outputs and exits if invalid.
(a valid row has 1-9 on a 9 square row)
I've been staring at my logic for 30 minutes and can't see why a board that I know is valid keeps spitting out invalid.
To try and make it a little easier to read, here's the part in question...
void* checkRow(void* p){
int check[9] = {0};
parameters* temp = (parameters*) p;
int tempRow = temp -> row;
int tempCol = temp -> col;
for (int i = 0; i < SIZE; i++){ // looping to find each # 1-9
for (int j = 0; j < SIZE; j++){
if (board[i][j] == 1)
check[0] = 1;
if (board[i][j] == 2)
check[1] = 1;
if (board[i][j] == 3)
check[2] = 1;
if (board[i][j] == 4)
check[3] = 1;
if (board[i][j] == 5)
check[4] = 1;
if (board[i][j] == 6)
check[5] = 1;
if (board[i][j] == 7)
check[6] = 1;
if (board[i][j] == 8)
check[7] = 1;
if (board[i][j] == 9) // changing value to 1 if found
check[8] = 1;
int k = 0;
while(k < 9){
if (check[k] == 0){
printf("invalid solution"); // should only print if 1-9 isn't found right?
exit(0);
}
k++;
}
memset(check, 0, sizeof(check)); // resetting array to zero
}
}
}
Here's everything, just in case.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#define SIZE 9
typedef struct{ // referenced from assignment page
int row;
int col;
} parameters;
int board[SIZE][SIZE]; // global variable holding board
pthread_t tRow, tCol, t1, t2, t3, t4, t5, t6, t7, t8, t9;
void setThreads();
void* checkRow(void* p);
int main(int argc, char **argv){ // referenced project 1. Supplies command line input for file
FILE *fp;
fp = fopen(argv[1], "r");
if (fp == NULL) // validity check
exit(1);
for (int i = 0; i < SIZE; i++){
for(int j = 0; j < SIZE; j++){
fscanf(fp, "%d", &board[i][j]);
}
}
setThreads();
printf("rows check out");
return 0;
}
void setThreads(){
parameters *rowcolparameter = (parameters *) malloc(sizeof(parameters));
rowcolparameter -> row = 0;
rowcolparameter -> col = 0;
parameters *square1 = (parameters *) malloc(sizeof(parameters));
square1 -> row = 0;
square1 -> col = 0;
parameters *square2 = (parameters *) malloc(sizeof(parameters));
square2 -> row = 0;
square2 -> col = 3;
parameters *square3 = (parameters *) malloc(sizeof(parameters));
square3 -> row = 0;
square3 -> col = 6;
parameters *square4 = (parameters *) malloc(sizeof(parameters));
square4 -> row = 3;
square4 -> col = 0;
parameters *square5 = (parameters *) malloc(sizeof(parameters));
square5 -> row = 3;
square5 -> col = 3;
parameters *square6 = (parameters *) malloc(sizeof(parameters));
square6 -> row = 3;
square6 -> col = 6;
parameters *square7 = (parameters *) malloc(sizeof(parameters));
square7 -> row = 6;
square7 -> col = 0;
parameters *square8 = (parameters *) malloc(sizeof(parameters));
square8 -> row = 6;
square8 -> col = 3;
parameters *square9 = (parameters *) malloc(sizeof(parameters));
square9 -> row = 6;
square9 -> col = 6;
pthread_create(&tRow, NULL, checkRow, rowcolparameter);
pthread_join(tRow, NULL);
}
void* checkRow(void* p){
int check[9] = {0};
parameters* temp = (parameters*) p;
int tempRow = temp -> row;
int tempCol = temp -> col;
for (int i = 0; i < SIZE; i++){ // looping to find each # 1-9
for (int j = 0; j < SIZE; j++){
if (board[i][j] == 1)
check[0] = 1;
if (board[i][j] == 2)
check[1] = 1;
if (board[i][j] == 3)
check[2] = 1;
if (board[i][j] == 4)
check[3] = 1;
if (board[i][j] == 5)
check[4] = 1;
if (board[i][j] == 6)
check[5] = 1;
if (board[i][j] == 7)
check[6] = 1;
if (board[i][j] == 8)
check[7] = 1;
if (board[i][j] == 9)
check[8] = 1;
int k = 0;
while(k < 9){
if (check[k] == 0){
printf("invalid solution"); // it should only say invalid if 1-9 wasn't found right?
exit(0);
}
k++;
}
memset(check, 0, sizeof(check)); // resetting array to 0
}
}
}
Thank you.

It seems that the "check part" is inside the inner loop! Shouldn't it be outside the inner loop. Like:
for (int i = 0; i < SIZE; i++){ // looping to find each # 1-9
for (int j = 0; j < SIZE; j++){
if (board[i][j] == 1)
check[0] = 1;
if (board[i][j] == 2)
check[1] = 1;
if (board[i][j] == 3)
check[2] = 1;
if (board[i][j] == 4)
check[3] = 1;
if (board[i][j] == 5)
check[4] = 1;
if (board[i][j] == 6)
check[5] = 1;
if (board[i][j] == 7)
check[6] = 1;
if (board[i][j] == 8)
check[7] = 1;
if (board[i][j] == 9) // changing value to 1 if found
check[8] = 1;
} // End the inner loop
// Now do the check
int k = 0;
while(k < 9){
if (check[k] == 0){
printf("invalid solution"); // should only print if 1-9 isn't found right?
exit(0);
}
k++;
}
memset(check, 0, sizeof(check)); // resetting array to zero
}
BTW: you can reduce the inner-loop code a lot like this:
// inner loop
for (int j = 0; j < SIZE; j++){
if (board[i][j] < 1 || board[i][j] > 9) exit(1); // Illegal board value
check[board[i][j] - 1] = 1; // Mark value as found
}

Related

confused about dynamic programming state

I was trying to solve the problem where if I was given an array of int which allows duplicate,
I need to find the count of how many permutation of this array there are such that each adjacent pair of integer in the array whose sum is a perfect square. I have derived the dp solution, but it was wrong, I looked at the solution, it was very similar to mine but with slight difference, can someone please look at it and tell me why mines won't work but the sample answer does?
My train of thought is, if I have g[i][j] == 1 telling me i and j forms a pair whose sum is a perfect square, 0 otherwise. And I have a dp[s][j] tells me if my node visited state is s, whose binary representation tells me all the node index that I have visited, and it ends in node with index j, I need DP for hamitonian path in a graph to calculate all possible ways to reach state s that ends in node index j, then the answer will be the sum of state s where all node is visited and it ends in node from 0 to n - 1. In terms of avoiding duplicate, I sort the input array of number and if in same layer of search, if we have nums[i - 1] == nums[i] but we have not visited nums[i], it means we just back out from an earlier dfs that visited the same number, we will not do that again.
I will paste the code here
The below is my answer, which will fail if the array contains duplicate
int n = nums.length;
int[][] dp = new int[1 << n][n];
int[][] g = new int[n][n];
Arrays.sort(nums);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(i != j && (Math.ceil(Math.sqrt(nums[i] + nums[j])) ==
Math.sqrt(nums[i] + nums[j]))) {
g[i][j] = 1;
}
}
}
for(int s = 0; s < (1 << n); s++) {
for(int j = 0; j < n; j++) {
if(s == (1 << j)) {
dp[1 << j][j] = (j == 0 || nums[j - 1] != nums[j]) ? 1 : 0;
continue;
}
if((s & (1 << j)) == 0) continue;
for(int i = 0; i < n; i++) {
if(g[i][j] == 0) continue;
if((s & (1 << i)) == 0) continue;
if(i > 0 && nums[i - 1] == nums[i] && ((s & (1 << (i - 1))) == 0)) continue;
dp[s][j] += dp[s & ~(1 << j)][i];
}
}
}
int res = 0;
int finish = (1 << n) - 1;
for(int i = 0; i < n; i++) {
res += dp[finish][i];
}
return res;
The below is the sample answer:
int n = nums.length;
boolean[][] g = new boolean[n][n];
int[][] dp = new int[1 << n][n];
Arrays.sort(nums);
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
if(Math.floor(Math.sqrt(nums[i] + nums[j])) * Math.floor(Math.sqrt(nums[i] + nums[j])) == nums[i] + nums[j]) {
g[i][j] = g[j][i] = true;
}
}
}
for(int i = 0; i < nums.length; i++) {
if(i == 0 || (i > 0 && nums[i - 1] != nums[i]))
dp[1 << i][i] = 1;
}
for(int s = 0; s < (1 << n); s++) {
for(int j = 0; j < n; j++) {
if((s & (1 << j)) == 0) continue;
for(int i = 0; i < n; i++) {
if(g[i][j]) {
if((s & (1 << i)) != 0) continue;
if(i > 0 && nums[i] == nums[i - 1] && ((s & (1 << (i - 1))) == 0)) continue;
dp[s | (1 << i)][i] += dp[s][j];
}
}
}
}
int ans = 0;
for(int l = 0; l < n; l++) {
ans += dp[(1 << n) - 1][l];
}
return ans;

Am I getting a segmentation fault due to an incorrect realloc?

struct model
{
char *cam;
int *to_location, *go_location;
int to_count, go_count;
int length, size;
};
struct model *
initialize(int l)
{
struct model *c;
c = (struct model *)malloc(sizeof(struct model));
assert(c != NULL);
c->length = l;
c->size = 2 * l;
c->cam = (char *)malloc(2 * l * sizeof(char));
assert(c->cam != NULL);
c->to_location = (int *)malloc(l * sizeof(int));
assert(c->to_location != NULL);
c->go_location = (int *)malloc(l * sizeof(int));
assert(c->go_location != NULL);
return c;
}
void
shuffle(struct model *current, struct model *future, int to, int g)
{
int i1, k, d1;
char init[100000];
current->to_count = 0;
current->go_count = 0;
for (i1 = 0; i1 < g; i1++)
{
init[i1] = 'G';
}
for (i1 = g; i1 < g + to; i1++)
{
init[i1] = 'T';
}
for (i1 = g + to; i1 < current->length; i1++)
{
init[i1] = '.';
}
for(i1 = 0; i1 < future->length; i1++)
{
d1 = rand() % current->length;
current->cam[i1] = init[d1];
if (current->cam[i1] == 'T')
{
current->to_location[current->to_count] = i1;
current->to_count = current->to_count + 1;
}
if (current->cam[i1] == 'G')
{
current->go_location[current->go_count] = i1;
current->go_count = current->go_count + 1;
}
for (k = d1; k < current->length; k++)
{
init[k] = init[k + 1];
}
current->length = current->length - 1;
}
current->length = future->length;
}
void
display(struct model *current)
{
int i;
printf("\n<");
current->to_count = 0;
current->go_count = 0;
for(i = 0; i < current->length; i++)
{
if (current->cam[i] == 'T')
{
current->to_location[current->to_count] = i;
current->to_count = current->to_count + 1;
}
else if (current->cam[i] == 'G')
{
current->go_location[current->go_count] = i;
current->go_count = current->go_count + 1;
}
printf("%c", current->cam[i]);
}
printf(">\n");
printf("\nThe total number of to's are %d, and the total number of gos are %d. The length is %d\n", current->to_count, current->go_count, current->length);
}
void
insert(struct model *current, struct model *future)
{
int j, k;
k = rand() % (current->length + 1);
current->length = current->length + 1;
for (j = current->length; j > k; j--)
{
future->cam[j] = future->cam[j - 1];
}
future->cam[k] = 'T';
future->size = 2 * current->length;
future->cam = (char *)realloc(future->cam, future->size * sizeof(char));
assert(future->cam != NULL);
current->size = 2 * current->length;
current->cam = (char *)realloc(current->cam, current->size * sizeof(char));
assert(current->cam != NULL);
}
int
main()
{
int l, to, go, i, k1, k2, j;
l = 100; //l,go,to are positive
go = 20;
to = 20; //go+to cannot be greater than l
struct model *current = initialize(l), *future = initialize(l);
shuffle(current, future, to, go);
display(current);
for (i = 0; i < 500; i++)
{
for (j = 0; j < current->length; j++)
{
future->cam[j] = current->cam[j];
}
insert(current, future);
for (j = 0; j < current->length; j++)
{
current->cam[j] = future->cam[j];
}
display(current);
}
return 0;
}
I am not able to find out the reason for a segmentation fault. I checked to see if I had implemented realloc correctly but from what I can tell there might not be a mistake there. the segmentation fault occurs after current->length reaches 281, so reallocation may be occurring uptill there as the initial size is 200 but why does it stop after that?
In initialize() you:
c->cam = (char *)malloc(2 * l * sizeof(char));
assert(c->cam != NULL);
c->to_location = (int *)malloc(l * sizeof(int));
assert(c->to_location != NULL);
c->go_location = (int *)malloc(l * sizeof(int));
assert(c->go_location != NULL);
And then in insert() you:
current->length = current->length + 1;
....
future->size = 2 * current->length;
future->cam = (char *)realloc(future->cam, future->size * sizeof(char));
assert(future->cam != NULL);
current->size = 2 * current->length;
current->cam = (char *)realloc(current->cam, current->size * sizeof(char));
And then in display() you:
current->to_count = 0;
current->go_count = 0;
for(i = 0; i < current->length; i++)
...
current->to_location[current->to_count] = i;
current->to_count = current->to_count + 1;
...
current->go_location[current->go_count] = i;
current->go_count = current->go_count + 1;
A similar thing also happens in shuffle()
So you write to to to_location from 0 up to current->length and current->length continues getting bigger because of insert() and yet to_location does NOT get bigger so as soon as current->length is increased you write past the end of the to_location array and clobber something important - eventually killing the program.

Minesweeper revealing cells in C

I am trying to write a minesweeper program in C.
What I am trying to achieve here is when user steps on one cell, the cells near without bombs and hint numbers will be revealed.
For example, if x is the cell stepped on, o is an empty but concealed square, . is an empty but revealed cell and * is the bomb (hidden when playing of course):
x o o o o
o o o * o
o o o o o
will result in:
. . 1 o o
. . 1 * o
. . 1 o o
Here is part of the code:
while (1)
{
printf("Row? ");
scanf("%d", &row);
printf("column? ");
scanf("%d", &clos);
if (row < 9 && row >= 0 && clos < 8 && clos >= 0)
break;
printf("\nInvalid Location\n\n");
}
if (real_map[row][clos] =='*')
{
print_map_win(display_map,real_map);
printf("\n");
printf("Flags Left = %d\n\n\n", flag_left);
printf("Game Over\n");
exit(0);
}
else
{
if (real_map[row][clos] == ' ')
{
display_map[row][clos] = real_map[row][clos];
bonos_reveal(display_map, real_map, clos, row);
// [[[bonos_reveal is the function I am asking for]]]
printf("\n");
}
else
{
display_map[row][clos] = real_map[row][clos];
}
}
in which real_map has the hint number and bombs in it, and display_map is the current state of the map.
edit: I have the following code, and it only reveals in one direction:
int bonos_reveal(int disp_map[MAP_ROWS][MAP_COLS], int real_map[MAP_ROWS][MAP_COLS], int clos, int row)
{
disp_map[row][clos] = real_map[row][clos];
if (row < 9 && row >= 0 && clos < 8 && clos >= 0)
{
if (real_map[row][clos+1] == ' ')
{
bonos_reveal(disp_map, real_map, clos + 1, row);
}
else
{
disp_map[row][clos+1] = real_map[row][clos+1];
return 1;
}
}
else
{
return 1;
}
return 1;
}
I have no idea how to loop through the cells.
Okay, here's an example implementation. It uses the following values for tiles:
0 to 8: an unmined tile; the number represents the pre-calculated number of adjacent mines
9: a mine; this special value is defined as BOMB.
Covered tiles have 10 added to that, flagged tiles (not used here) have 20 added to that. You can test whether a tile is mined with:
board[row][col] % 10 == BOMB
I'll let the code do the explaining:
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define ROWS 12
#define COLS 20
#define BOMBS 8
#define BOMB 9
void inc(int board[ROWS][COLS], int row, int col)
{
if (row < 0 || row >= ROWS) return;
if (col < 0 || col >= COLS) return;
if (board[row][col] % 10 == BOMB) return;
board[row][col]++;
}
/*
* Set up board and pre-calculate adjacent bombs
*/
void board_init(int board[ROWS][COLS])
{
int i, j, n;
for (j = 0; j < ROWS; j++) {
for (i = 0; i < COLS; i++) {
board[j][i] = 10;
}
}
n = 0;
while (n < BOMBS) {
j = rand() % ROWS;
i = rand() % COLS;
if (board[j][i] % 10 != BOMB) {
board[j][i] = 19;
inc(board, j - 1, i - 1);
inc(board, j - 1, i);
inc(board, j - 1, i + 1);
inc(board, j, i - 1);
inc(board, j, i + 1);
inc(board, j + 1, i - 1);
inc(board, j + 1, i);
inc(board, j + 1, i + 1);
n++;
}
}
}
/*
* Reveal tile and propagate revelation
*/
void board_reveal(int board[ROWS][COLS], int row, int col)
{
if (row < 0 || row >= ROWS) return; /* skip off-board tiles */
if (col < 0 || col >= COLS) return;
if (board[row][col] < 10) return; /* already revealed, skip */
if (board[row][col] >= 20) return; /* must remove flag first, skip */
if (board[row][col] % 10 == BOMB) {
int i, j;
printf("Bang!\n");
for (j = 0; j < ROWS; j++) {
for (i = 0; i < COLS; i++) {
if (board[j][i] % 10 == BOMB) board[j][i] = BOMB;
}
}
} else {
board[row][col] %= 10;
if (board[row][col] == 0) {
board_reveal(board, row - 1, col);
board_reveal(board, row, col - 1);
board_reveal(board, row, col + 1);
board_reveal(board, row + 1, col);
}
}
}
void board_print(int board[ROWS][COLS])
{
int i, j;
for (j = 0; j < ROWS; j++) {
putchar(' ');
for (i = 0; i < COLS; i++) {
const char *tile = ".12345678*##########PPPPPPPPPP";
int k = board[j][i];
putchar(tile[k]);
}
putchar('\n');
}
}
int main()
{
int board[ROWS][COLS];
srand(time(NULL));
board_init(board);
board_reveal(board, 0, 0);
board_print(board);
return 0;
}

Unusual behaviour in an OpenMP program

I have a program and i tried to use Open MP.
The output is still correct (i tested it after multiple runs), but the times i get are quite odd.
So the time for the single threaded version is 0.1 seconds.
With 2 treads i get 0.05, but with 4 i obtain 0.15 seconds.
How is this possible?
I am just using simple parallel for's.
#pragma omp parallel for private(i, j)
for(i = 1; i <= total_height; i++){
for(j = 1; j <= total_width; j++){
int current_neighbours = neighbours[i][j];
// if(i == 2 && j == 1)
// printf("%d%d\n", current_neighbours, neighbours[2][1]);
if(current_neighbours == 0 || current_neighbours == 1 || current_neighbours > 3){
if(map[i][j] == 1){
update_maps(i, j, 0);
}
}
else if(current_neighbours == 3){
if(map[i][j] == 0){
update_maps(i, j, 1);
}
}
}
}
The update_maps functions looks like this
void update_maps(int i, int j, int value){
map[i][j] = value;
int k, neighbouri, neighbourj;
int num_of_thread = omp_get_thread_num();
if(value == 0)
value = -1;
for(k = 0; k < 8 ; k++){
neighbouri = i + di[k];
neighbourj = j + dj[k];
if(in_map(neighbouri, neighbourj)){
neighbouri--;
neighbourj--;
modify[neighbouri * total_height + neighbourj + (total_height * total_width * num_of_thread)] += value;
}
}
}

Donald Knuth algorithm for Mastermind

I'm working onto the Donald Knuth 1977 algorithm for Mastermind (here). I've implemented some steps, but I don't know how to calculate the number of possibilites that would be eliminated for each possible score.
Integer Bulls <- 0
WHILE Bulls <= 4
Integer Cows <- 0
WHILE Cows <= 4
Integer CurrentSetSize <- 0
WHILE CurrentSetSize <= Set.size
// Now, I should know if this possibility can be eliminated. But how ?
END WHILE
END WHILE
END WHILE
Do you have any way to do this ?
Thanks.
Edit : I did it with C. It isn't Mastermind in reality but Bulls & Cows, but it's the same.
// ASCII-compatible
#define POSSIBILITIES 6720
struct Guess {
int i[5];
};
struct Answer {
int bulls;
int cows;
};
static struct Set {
struct Guess value;
int score;
} *CurrentSet;
void
initSet(void)
{
for (int i = 'a'; i <= 'h'; ++i) {
for (int j = 'a'; j <= 'h'; ++j) {
if (j == i) continue;
for (int k = 'a'; k <= 'h'; ++k) {
if (k == j || k == i) continue;
for (int l = 'a'; l <= 'h'; ++l) {
if (l == k || l == j || l == i) continue;
for (int m = 'a'; m <= 'h'; ++m) {
if (m == l || m == k || m == j || m == i) continue;
CurrentSet->value.i[0] = i;
CurrentSet->value.i[1] = j;
CurrentSet->value.i[2] = k;
CurrentSet->value.i[3] = l;
CurrentSet->value.i[4] = m;
CurrentSet->score = 0;
}
}
}
}
}
}
void
computeScore(int index)
{
struct answer p;
for (p.bulls = 0; p.bulls <= 4; ++p.bulls) {
for (p.cows = 0; p.cows <= 4; ++p.cows) {
for (int i = 0; i < POSSIBILITIES; ++i) {
}
}
}
}
void
updateSet(void)
{
for (int i = 0; i < POSSIBILITIES; ++i)
computeScore(i);
}

Resources