I am using eclipse 3.2020 on WIN10 and I have a problem executing my main function.
When I run the program as it is, I get no output to conole, even when I add a printf in the first line, and the exit code is -1,073,741,819. When I comment out/ delete the line solve(s); the code run as intended and gives exit code 0.
Edit: added full code (both solve and print_sol are in solver.c)
Edit 2: As mentioned in the comments, the problem was in the code (bug) and not eclipse, I just assumed that an error message will be printed if there is one.
p.s.: I still find the fact a printf in the start won't print if there is a runtime error in another part of the main function quite weird.
main.c:
#include "solver.h"
#include <stdlib.h>
int main(int argc, char** argv){
int **grid = (int**) malloc(sizeof(int*) * 4);
for (int i = 0; i < 4 ; i++){
grid[i] = (int*) malloc(sizeof(int) * 4);
}
int mat[4][4] = {{1,0,3,0}
,{2,0,0,0}
,{3,0,0,0}
,{4,2,0,0}};
for (int i = 0; i < 4; i++){
for (int j = 0; j < 4; j++){
grid[i][j] = mat[i][j];
}
}
solver *s = create_solver(4, &grid);
solve(s);
print_sol(s);
}
solver.h:
#ifndef SOLVER_H_
#define SOLVER_H_
typedef struct sudoku_solver solver;
/*creates a new solver using the length of one row of the board.
*Then, the user will follow the instructions on screen to input the board*/
solver* create_solver(int row_len, int ***input_board_ptr);
/*if solver is NULL, an error will appear.
*Otherwise, The board that was given won't be changed, and neither
*the solver nor the solution (unless saved before using get_sol)
*will be accessible after this*/
void destroy_solver(solver *solver);
/*if solver is NULL, an error will appear.
*Otherwise, it will solve the inputed board*/
void solve(solver *solver);
/*if "solve" wasn't executed before, an error will appear.
*Otherwise, it will print a solution to the inputed board*/
void print_sol(solver *solver);
/*if "solve" wasn't executed before, an error will appear.
*Otherwise, returns a solution to the inputed board as a matrix of integers*/
int** get_sol(solver *solver);
#endif /* SOLVER_H_ */
solver.c:
#include "solver.h"
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
/*the board will be represented by an array of size NxN.
*the value of every board cell is between 0 and N when 0
*means "default value"*/
typedef struct sudoku_solver{
/*length of one row of the board*/
int N;
/*a pointer to the solution board*/
int ***sol_ptr;
}solver;
solver* create_solver(int row_len, int ***input_board_ptr){
solver *s = (solver*) malloc(sizeof(solver));
/*throw an ERROR if the malloc failed*/
/*row_len is a variable, so we have to declare everything dynamically */
/*allocating the sol matrix as an array of pointers (1 out of 2D)*/
int **sol = (int**) malloc(row_len * sizeof(int*));
for (int i = 0; i < row_len; i++){
/*allocating every row (the second D)
*while making sol equal to input_board*/
sol[i] = (int*) malloc(row_len * sizeof(int));
for (int j = 0; j < row_len; j++){
sol[i][j] = (*input_board_ptr)[i][j];
}
}
s->N = row_len;
/*if row_len != pow(sqrt(row_len),2) then throw invalid input ERROR*/
s->sol_ptr = /
return s;
}
void destroy_solver(solver *s){
for (int i = 0; i < s->N; i++){
free((*(s->sol_ptr))[i]);
}
free(*(s->sol_ptr));
free(s->sol_ptr);
free(s);
}
int* calc_next(int x, int y, int *next, solver *s);
bool isSafe(int x, int y, int val, solver *s);
bool solve_rec(int x, int y, solver *s);
void solve(solver *s){
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
//find next empty space
if ((*sp)[0][0] == 0){
next[0] = 0;
next[1] = 1;
}
else{
calc_next(0, 0, next, s);
}
int nextX = next[0];
int nextY = next[1];
for (int i = 1; i < n; i++){
if (isSafe(nextX, nextY, i, s)){
(*sp)[nextX][nextY] = i;
if(solve_rec(nextX, nextY, s)){
return;
}
//backtrack
(*sp)[nextX][nextY] = 0;
}
}
printf("no sol");
return;
}
bool solve_rec(int x, int y, solver *s){
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
if (x == n - 1 && y == n - 1){
return true;
}
//find next empty space
calc_next(x, y, next, s);
int nextX = next[0];
int nextY = next[1];
for (int i = 1; i < n; i++){
if (isSafe(nextX, nextY, i, s)){
(*sp)[nextX][nextY] = i;
if(solve_rec(nextX, nextY, s)){
return true;
}
//backtrack
(*sp)[nextX][nextY] = 0;
}
}
return false;
}
bool isSafe(int x, int y, int val, solver *s){
int n = s->N;
int ***sp = s->sol_ptr;
/*check row*/
for (int j = 0; j < n; j++){
if ((*sp)[x][j] == val){
return false;
}
}
/*check col*/
for (int i = 0; i < n; i++){
if ((*sp)[i][y] == val){
return false;
}
}
/*check block
*the index of a block in a grid is just like the index of entry in block.
*In sudoku, there are bs*bs blocks, and each has bs rows and bs columns*/
int bs = sqrt(n); // block size
int block_x_index = x / bs;
int block_y_index = y / bs;
for(int i = block_x_index * bs; i < bs * (block_x_index + 1); i++){
for(int j = block_y_index * bs; j < bs * (block_y_index + 1); j++){
if ((*sp)[i][j] == val){
return false;
}
}
}
return true;
}
/*assuming x,y is not the last place in the grid,
* finds the next empty place after it*/
int* calc_next(int x, int y, int *next, solver *s){
int n;
int ***sp = s->sol_ptr;
/*find the first empty place*/
do{
n = s->N;
if (y == n - 1){
x++;
y = 0;
}
else{
y++;
}
}while ((*sp)[x][y] != 0);
next[0] = x;
next[1] = y;
return next;
}
void print_sol(solver *s){
int n = s->N;
int bs = sqrt(n); // block size
char curr;
int rows_passed, col_passed;
for (int i = 0; i < n + bs - 1; i++){
for (int j = 0; j < n + bs - 1; j++){
//if it's a grid row
if (i == bs || ((i - bs) % (bs + 1)) == 0){
//if it's also a grid col
if (j == bs || ((j - bs) % (bs + 1) == 0)){
curr = '+';
}
else{
curr = '-';
}
}
//if it's only a grid col
else if (j == bs || ((j - bs) % (bs + 1) == 0)){
curr = '|';
}
else{
rows_passed = i / (bs + 1);
col_passed = j / (bs + 1);
curr = '0' + (*(s->sol_ptr))[i-rows_passed][j-col_passed];
}
printf("%c",curr);
}
printf("\n");
}
}
int** get_sol(solver *solver){
return *(solver->sol_ptr);
}
Thank you.
Please learn how to use your debugger. In this case, it would take you directly to the problem: you're crashing with an access violation (Windows 0xc0000005) here:
void solve(solver *s) {
int n = s->N;
int next[2];
int ***sp = s->sol_ptr;
//find next empty space
if ((*sp)[0][0] == 0) { // <-- Access violation here: "sp" incorrectly initialized!
next[0] = 0;
next[1] = 1;
}
The underlying problem is that although sudoku_solver.N was initialized to "4" ... sudoku_solver.sol_ptr[0][0] is pointing to uninitialized memory.
PS:
Yes, it's very definitely "executing". It wouldn't crash if it didn't run ;)
Related
I hope i made my self clear enough in the title but if not i am here to explain my self
i got an array from an input ( like Arr = {, ).
we can use only 1 additional array (1 original 1 additional)
this is what i made so far :
I made a new array named newArr and assigned it all the values Arr contains.
i sorted it (because its requires time complexity of nlogn)
and then moved duplicates to the end.
now what i can't figure out :
now i need to move the original digits to their place according to the main
(all the values in the arrays are positive and they can be bigger then
n-which is the size of the array and ofc they can be also smaller then n)
i also need to return the number of original digits in the array
the original number should stay in the same position and the duplicates in the end of the array their order doesn't matter.
from here we can't use another additional array only the current arrays that we have ( which are 2)
i have been thinking about doing some kind of binary search but all of them went wrong.(like bin_search_first) and original binary and still couldn't manage it.
can some one give me an hint?
here is the code at where i am
#define _CRT_SECURE_NO_WARNINGS
/*Libraries*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
int* input_array(int);
int moveDuplicatesV2(int*, int);
void merge(int* a, int p, int q, int r);
void merge_sort(int* a, int first, int last);
void swap(int* v, int* u);
int bin_search_first(int , int* , int );
int main()
{
int arr[10] = { };
int n = 12;
int k = 0;
int first = 0;
int last = n - 1;
int mid = (first + last) / 2;
int l = n - 1;
int* D = arr + 1;
int j = 0;
size_t dupes_found = 0;
int* newArr = (int*)malloc(12 * sizeof(int));
assert(newArr);
for (int i = 0; i < n; i++)
{
newArr[i] = arr[i];
}
merge_sort(newArr, first, last);
for (size_t i = 0; i < n - 1 - dupes_found;)
{
if (newArr[i] == newArr[i + 1])
{
dupes_found++;
int temp = newArr[i];
memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
newArr[n - 1] = temp;
}
else {
i++;
}
}
j = 0;
int key = 0;
first = 0;
for (int i = 0; i < n - dupes_found; i++)
{
key = newArr[i];
first = bin_search_first(key, arr,n);
swap(&newArr[i], &newArr[first]);
newArr[first] = newArr[i];
}
for (int i = 0; i < n; i++)
{
arr[i] = newArr[i];
}
for (int i = 0; i < n; i++)
{
printf("%d", arr[i]);
}
return n - dupes_found;
}
void merge(int* a, int p, int q, int r)
{
int i = p, j = q + 1, k = 0;
int* temp = (int*)malloc((r - p + 1) * sizeof(int));
assert(temp);
while ((i <= q) && (j <= r))
if (a[i] < a[j])
temp[k++] = a[i++];
else
temp[k++] = a[j++];
while (j <= r)
temp[k++] = a[j++];
while (i <= q)
temp[k++] = a[i++];
/* copy temp[] to a[] */
for (i = p, k = 0; i <= r; i++, k++)
a[i] = temp[k];
free(temp);
}
void merge_sort(int* a, int first, int last)
{
int middle;
if (first < last) {
middle = (first + last) / 2;
merge_sort(a, first, middle);
merge_sort(a, middle + 1, last);
merge(a, first, middle, last);
}
}
void swap(int* v, int* u)
{
int temp;
temp = *v;
*v = *u;
*u = temp;
}
int bin_search_first(int key, int* a, int n)
{
int low, high, mid;
low = 0;
high = n - 1;
while (low <= high)
{
mid = (low + high) / 2; // low + (high - low) / 2
if (key > a[mid])
low = mid + 1;
else
if (key < a[mid])
high = mid - 1;
else //key==a[mid]
if ((low == high) || (a[mid - 1] < key))
return mid;
else
high = mid - 1;
}
return -1;
}
Here is my idea:
Sort the array (nlogn)
Loop over the array and for each value, save a pointer to its first occurence (n)
Loop over the original array and insert the value into a result array if it is the values first occurrence. Whether or not it is the first occurrence can be checked using the sorted array: each element in this array has an additional flag that will be set if the value has already been seen. So, search for the element using bsearch, if seen append to back of result array (order does not matter), if not seen append to beginning of array and set seen value. (nlogn, since bsearch doesn't need to seek the first element because it was precomputed thus logn, over the array n)
Here is an example code (you can replace the qsort by mergesort to make the algorithm actually nlogn, I just used qsort because it is given):
#include <stdio.h>
#include <stdlib.h>
struct arr_value {
int value;
int seen;
struct arr_value *first;
};
int compar(const void *p1,const void *p2) {
struct arr_value *v1 = (struct arr_value *)p1;
struct arr_value *v2 = (struct arr_value *)p2;
if(v1->value < v2->value) {
return -1;
} else if(v1->value == v2->value) {
return 0;
}
return 1;
}
int main()
{
#define NumCount (12)
int arr[NumCount] = { 7, 3, 1, 2, 7, 9, 3, 2, 5, 9, 6, 2 };
int arrResult[NumCount];
int resultCount = 0;
int resultCountBack = 0;
struct arr_value arrseen[NumCount];
for(int i = 0; i < NumCount; ++i) {
arrseen[i].value = arr[i];
arrseen[i].seen = 0;
}
qsort(arrseen, NumCount, sizeof(struct arr_value), compar);
struct arr_value *firstSame = arrseen;
firstSame->first = firstSame;
for(int i = 1; i < NumCount; ++i) {
if(arrseen[i].value != firstSame->value) {
firstSame = arrseen + i;
}
arrseen[i].first = firstSame;
}
struct arr_value key;
for(int i = 0; i < NumCount; ++i) {
key.value = arr[i];
struct arr_value *found = (struct arr_value *)bsearch(&key, arrseen, NumCount, sizeof(struct arr_value), compar);
struct arr_value *first = found->first;
if(first->seen) {
// value already seen, append to back
arrResult[NumCount - 1 - resultCountBack] = first->value;
++resultCountBack;
} else {
// value is new, append
arrResult[resultCount++] = first->value;
first->seen = 1;
}
}
for(int i = 0; i < NumCount; ++i) {
printf("%d ", arrResult[i]);
}
return 0;
}
Output:
7 3 1 2 9 5 6 2 9 2 3 7
To begin with, memmove doesn't run in a constant time, so the loop
for (size_t i = 0; i < n - 1 - dupes_found;)
{
if (newArr[i] == newArr[i + 1])
{
dupes_found++;
int temp = newArr[i];
memmove(&newArr[i], &newArr[i + 1], sizeof(int) * (n - i - 1));
newArr[n - 1] = temp;
}
else {
i++;
}
}
drives the time complexity quadratic. You have to rethink the approach.
It seems that you are not using a crucial point:
all the values in the arrays are positive
It seriously hints that changing values to their negatives is a way to go.
Specifically, as you iterate over the initial array, and bin-search its elements in temp, comparing the _ absolute values_. When an element is found in temp, and it is still positive there, flip all its dupes in temp to negative. Otherwise flip it in initial.
So far, it is O(n log n).
Then perform an algorithm known as stable_partition: all positives are moved in front of negatives, retaining the order. I must not spell it here - I don't want to deprive you of a joy figuring it out yourself (still O(n log n)
And finally flip all negatives back to positives.
I have written a program in C. The problem is when I compile this program in a Linux/Unix environment I get a segfault. But when I compile it in Windows with minGW It works fine. Basically in the program I have a multidimensional array. When I compile and debug in gdb in Linux/Unix I lose one row of the multidimensional array randomly. When I try to access every column in that row all of them suddenly cannot be accessed. My whole row gets lost.
Error:Program received signal SIGSEGV, Segmentation fault.
Note: isItDone(), oneToTwo(), and checkAroundTwo() are very likely not the problem. I tried running program without them and it still showed the error.
The code:
int main( int argc, char *argv[] ){
FILE * output;
output = fopen("output.txt", "w");
srand(time(NULL));
int size = 0; // Resetting before taking arguments
int evaltime = 0; // Resetting before taking arguments
int rand1, rand2;
int counter, counter2, counter3;
if(argc == 3){
size = atoi(argv[1]);
evaltime = atoi(argv[2]);
}
else{
return 0;
}
double *evaltimes = (double*)calloc(evaltime , sizeof(double)); // The array of the results we got.
for(counter2 = 0; counter2 < evaltime; counter2++){
int cellnumbers = 0;
int **ground = (int**)malloc(size * sizeof(int)); //Mallocating for every iteration
for(counter = 0; counter < size; counter++){
ground[counter] = (int*)calloc(size, sizeof(int)); // Initializing all the 0.
}
while(!isItDone(ground, size)){ // It's finished when last row is 2.
rand1 = rand() % size;
rand2 = rand() % size; // Take two random numbers for picking in array limit.
printf("%d %d\n", rand1, rand2);
if(rand1 == 0){ // Is it a top cell
if(ground[rand1][rand2] == 0){
ground[rand1][rand2] = 2;
cellnumbers++; // Increment when a cell is picked.
}
}
else{
if(ground[rand1][rand2] == 1 || ground[rand1][rand2] == 2) // The cell is already opened
continue;
else{
ground[rand1][rand2] = 1; // Defaulting to 1 before control
cellnumbers++;
oneTotwo(ground, size, rand1, rand2);
}
}
}
if(counter2 == evaltime - 1){ // Printing the last variation
for(counter3 = 0; counter3 < size; counter3++){
for(counter = 0; counter < size; counter++){
fprintf(output, "%d ",ground[counter3][counter]);
}
fprintf(output, "\n");
}
}
evaltimes[counter2] = (double)cellnumbers / (double)(size*size);
for(counter = 0; counter < size; counter++)
free(ground[counter]);
free(ground);
}
double meany = mean(evaltimes, evaltime);
double stddeviation = stddev(evaltimes, evaltime, meany);
fprintf(output, "mean() = %f \n", meany);
fprintf(output, "stddev() = %f",stddeviation);
fclose(output);
return 0;
}
I think the bug is most likely lies in main but here are my functions.
int isItDone(int **p, int size){
int counter;
for(counter = 0; counter < size; counter++){
if(p[size - 1][counter] == 2 && (p + size - 1) != 0)
return 1;
}
return 0;
}
void oneTotwo(int **p, int size, int rand1, int rand2){
//Checking the Upper Cells
if(rand1 < size - 1){ // Making sure no control if it is the last cell.
if(p[rand1 + 1][rand2] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand1 > 0){
if(p[rand1 - 1][rand2] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand2 < size - 1){
if(p[rand1][rand2 + 1] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
if(rand2 > 0){
if(p[rand1][rand2 - 1] == 2){
p[rand1][rand2] = 2;
checkAroundTwo(p, size, rand1, rand2);
}
}
}
void checkAroundTwo(int **p, int size, int rand1, int rand2){
if(rand1 < size - 1){
if(p[rand1 + 1][rand2] == 1){
p[rand1 + 1][rand2] = 2;
checkAroundTwo(p, size, rand1 + 1, rand2);
}
}
if(rand1 > 0){
if(p[rand1 - 1][rand2] == 1){
p[rand1 - 1][rand2] = 2;
checkAroundTwo(p, size, rand1 - 1, rand2);
}
}
if(rand2 < size - 1){
if(p[rand1][rand2 + 1] == 1){
p[rand1][rand2 + 1] = 2;
checkAroundTwo(p, size, rand1, rand2 + 1);
}
}
if(rand2 > 0){
if(p[rand1][rand2 - 1] == 1){
p[rand1][rand2 - 1] = 2;
checkAroundTwo(p, size, rand1, rand2 - 1);
}
}
}
double mean(double *p, int size){
double sum = 0.0000000;
int counter;
for(counter = 0; counter < size; counter++)
sum += p[counter];
return sum / (double)(size);
}
double stddev(double *p, int size, double mean){
double sum = 0.0000000;
int counter;
for(counter = 0; counter < size; counter++)
sum += sqr(((double)p[counter] - mean));
return sqrt(sum / (double)(size - 1));
}
double sqr(double x){
return x*x;
}
double sqrt(double x){
int counter = 0;
while(sqr(counter) < x){
counter++;
}
double s = counter;
for(counter = 0; counter < 50; counter++){
s = (double)1/2 * (double)(s + x/s);
}
return s;
}
Let's assume int array[10][10]
One more weird thing is that in gdb when I for example lose array[5] row I try to access it from the row before it. For example with array[4][10]. When I do it "array[4][10] = 49". Why is this? Rest is (array[4][12], array[4][13] etc.) is 0 as I specified. Why suddenly the first element of the 5th row achieved from the 4th row becomes 49 ? That I dont understand.
When you assign memory to a 2D array, you're assigning an array of pointers, each of which points to a block of memory.
This means when you do your initial malloc you need to assign ...sizeof(int*) and not ...sizeof(int).
In short, change this line:
int **ground = (int**)malloc(size * sizeof(int));
to:
int **ground = (int**)malloc(size * sizeof(int*));
I am a newbie to threading and i am trying to change the sequential program of travelling salesman problem (dynamic programming) to parallel program using threading in c.
#include <stdio.h>
#include <limits.h>
#define size 10 //maximum 10 cities
#define min(a,b) (a > b ? b : a)
#define sizePOW 1024 // 2^10
//Space complexity: O(n * 2^n)
//Time complexity: O(n^2 * 2^n)
int n; npow;
int g[size][sizePOW];
int p[size][sizePOW];
int adj[size][size];
int compute(int start, int set) {
int masked, mask, temp, i;
int result = INT_MAX; //result stores the minimum
if (g[start][set] != -1) //memoization DP top-down,check for repeated subproblem
return g[start][set];
for (i = 0; i < n; i++) { //npow-1 because we always exclude "home" vertex from our set
mask = (npow - 1) - (1 << i); //remove ith vertex from this set
masked = set & mask;
if (masked != set) { //in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
temp = adj[start][i] + compute(i, masked); //compute the removed set
if (temp < result)
result = temp,
p[start][set] = i; //removing ith vertex gave us minimum
}
}
return g[start][set] = result; //return minimum
}
void getpath(int start, int set) {
if (p[start][set] == -1)
return; //reached null set
int x = p[start][set];
int mask = (npow - 1) - (1 << x);
int masked = set & mask; //remove p from set
printf("%d ", x);
getpath(x, masked);
}
void TSP() {
int i, j;
//g(i,S) is length of shortest path starting at i visiting all vertices in S and ending at 1
for (i = 0; i < n; i++)
for (j = 0; j < npow; j++)
g[i][j] = p[i][j] = -1;
for (i = 0; i < n; i++)
g[i][0] = adj[i][0]; //g(i,nullset)= direct edge between (i,1)
int result = compute(0, npow - 2);//npow-2 to exclude our "home" vertex
printf("Tour cost:%d\n", result);
printf("Tour path:\n0 ");
getpath(0, npow - 2);
printf("0\n");
}
int main(void) {
int i, j;
printf("Enter number of cities\n");
scanf("%d",&n);
npow=(int)pow(2, n);//bit number required to represent all possible sets
printf("Enter the adjacency matrix\n");
for(i = 0; i < n; i++)
for(j = 0; j < n; j++)
scanf("%d", &adj[i][j]);
TSP();
return 0;
}
This is the sequential program from ideone code.
Here is my parallel code for this
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include<limits.h>
#define size 10 //maximum 10 cities
#define min(a,b) a > b ? b:a
#define sizePOW 1024 // 2^10
struct threadargs {
int a, b;
int *c;
};
//Space complexity: O(n * 2^n)
//Time complexity: O(n^2 * 2^n)
int n, npow;
int g[size][sizePOW];
int p[size][sizePOW];
int adj[size][size];
void printMatrix() {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 16; j++) {
printf("%d ",g[i][j]);
printf("\n");
}
printf("\n\n");
}
void *compute(void *args) {
int masked, mask, i, start, set;
int result = INT_MAX; //result stores the minimum
struct threadargs *recvargs = (struct threadargs *) args;
start = recvargs->a;
set = recvargs->b;
int *retval = recvargs->c;
if (g[start][set] != -1) { //memoization DP top-down,check for repeated subproblem
*retval += g[start][set];
return;
}
printMatrix();
//sleep(1);
int temp[n];
for (i = 0; i < n; i++)
temp[i] = INT_MAX;
pthread_t threads[n];
struct threadargs arguments[n];
int running_thread_count = 0;
for (i = 0; i < n; i++)
threads[i] == -1;
for (i = 0; i < n; i++) { //npow-1 because we always exclude "home" vertex from our set
mask= (npow - 1) - (1 << i); //remove ith vertex from this set
masked = set & mask;
//printf("hello world");
if (masked != set)//in case same set is generated(because ith vertex was not present in the set hence we get the same set on removal) eg 12&13=12
{
temp[i] = adj[start][i];
arguments[i].a = i;
arguments[i].b = masked;
arguments[i].c = &temp[i];
pthread_create(&threads[i], NULL, compute, (void *)&arguments[i] );
running_thread_count++;
}
}
for (i = 0; i < n; i++) {
if (pthread_kill(threads[i], 0) != ESRCH)
pthread_join(threads[i], NULL);
}
int ith = 0;
result = temp[0];
for (i = 1; i < n; i++) {
if(temp[i] < result) {
result = temp[i];
ith = i;
}
}
p[start][set] = ith;
if (result != INT_MAX)
g[start][set] = result; //return minimum
*retval += g[start][set];
}
void getpath(int start,int set)
{
if (p[start][set] == -1)
return; //reached null set
int x = p[start][set];
int mask= (npow - 1) - (1 << x);
int masked = set & mask;//remove p from set
printf("%d ",x);
getpath(x, masked);
}
void TSP()
{ int i, j;
//g(i,S) is length of shortest path starting at i visiting all vertices in S and ending at 1
for(i=0; i < n; i++)
for( j = 0; j < npow; j++)
g[i][j] = p[i][j] = -1;
for (i = 0; i < n; i++)
g[i][0] = adj[i][0]; //g(i,nullset)= direct edge between (i,1)
int result;
struct threadargs arguments;
arguments.a = 0;
arguments.b = npow-2;
arguments.c = &result;
compute((void *) &arguments);//npow-2 to exclude our "home" vertex
printf("Tour cost:%d\n",result);
printf("Tour path:\n0 ");
getpath(0,npow-2);
printf("0\n");
}
int main(void) {
int i, j;
printf("Enter number of cities\n");
scanf("%d", &n);
npow=(int)pow(2, n);//bit number required to represent all possible sets
printf("Enter the adjacency matrix\n");
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &adj[i][j]);
TSP();
return 0;
}
But I am getting segmentation fault while trying to execute this code. Following is the output of the gdb
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff78bf63e in pthread_join (threadid=4196128,
thread_return=0x0) at pthread_join.c:85
85 pthread_join.c: No such file or directory.
(gdb) backtrace
#0 0x00007ffff78bf63e in pthread_join (threadid=4196128,
thread_return=0x0) at pthread_join.c:85
#1 0x0000000000400b36 in compute (args=0x7fffffffde90) at tsp3.c:69
#2 0x0000000000400db2 in TSP () at tsp3.c:107
#3 0x0000000000400ec8 in main () at tsp3.c:120
(gdb)
I know this will not give any noticeable performance gain but I want to try this. Thanks in advance.
**edit : **
I have rectified the errors but now I am facing new errors.I am getting correct answer when program runs but if I delete the line `printMatrix()
, I get segmentation fault. The gdb log is as follows
(gdb) backtrace
#0 __pthread_kill (threadid=0, signo=0)
at ../nptl/sysdeps/unix/sysv/linux/pthread_kill.c:42
#1 0x0000000000400c85 in compute (args=0x7ffff74eede0) at tsp3.c:79
#2 0x00007ffff78be182 in start_thread (arg=0x7ffff64ed700)
at pthread_create.c:312
#3 0x00007ffff75eaefd in clone ()
at ../sysdeps/unix/sysv/linux/x86_64/clone.S:111
(gdb)
why is this happening. Please explain. Thanks in advance.
You are creating threads in compare function, and you pass compare as thread function, that's chaos. You maybe exceed available number of threads.
#include <stdio.h>
#include <math.h>
int n=4;
int GetQueenSettings(int board[4][4],int currentRow,int n)
{
//decide when the recursion stops
if(currentRow==n)
return 1; //successful setting
//otherwise we set column by column in this row and continue
int TotalSettingCount=0;
for(int i=0;i<n;i++)
{
//make sure it can be set (it is unset at that moment)
if(board[currentRow][i]==0)
{
board[currentRow][i]==1+currentRow;
//use row related info for settings
//now set invalid positions for remaining rows
setInvalid(board,currentRow,n,i);
//recover after this before trying the next
TotalSettingCount += GetQueenSettings(board,currentRow+1,n);
board[currentRow][i]=0;
RecoverBoard(board,currentRow,n);
}
}
return TotalSettingCount;
}
void setInvalid(int board[4][4],int currentRow,int n,int i)
{
//vertical and diagonal elements
for(int row=currentRow+1;row<n;row++) //start from the next line
{
//firstly make sure board can be set
if(board[row][i]==0)//vertical position
board[row][i]=-(1+currentRow);
//now check diagonal
int rowGap=row-currentRow;
if(i-rowGap>=0 && board[row][i-rowGap]==0)
{
//left bottom diagonal position
board[row][i-rowGap]=-(1+currentRow);
}
if(i+rowGap<n && board[row][i+rowGap]==0)
{
//bottom right diagonal position
board[row][i+rowGap]=-(1+currentRow);
}
}
}
void RecoverBoard(int board[4][4],int currentRow,int n)
{
//recover is to check all remaining rows if index is higher than current row(setters)
//OR less than -currentRow(invalids)!
for(int row=currentRow+1;row<n;row++)
{
for(int col=0;col<n;col++)
{
if(board[row][col]>currentRow || board[row][col]< -currentRow)
board[row][col]=0;
}
}
}
int main()
{
int board[n][n];
printf("Number of settings:-> %d",GetQueenSettings(board,0,n));
return 0;
}
There are N queeens placed on a NxN chessboard without interfering with each other. when i run this code i get the answer as zero instead of 2 . also i cant figure out a way of passing array board to functions with variable size(size will be given by user).What am i doing wrong?!
You should initialize your board. As is, you start with a board full of garbage values. You are using a variable-length array as board. Such arrays cannot be initialized, so you have to set the board to all zero with a loop or with memset from <string.h>:
int board[n][n];
memset(board, 0, sizeof(board));
You can pass variable-length arrays to functions when the dimensions are passed in as earlier arguments, for example:
int GetQueenSettings(int n, int board[n][n], int currentRow) { ... }
Also fix the =/== switch in setInvalid:
if (board[row][i] == 0)
board[row][i] = -(1 + currentRow);
Finally make sure that all functions have proper prototypes when they are called.
A loooooooong time ago I developed an algorithm like the one you have, maybe it can help you.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long Solutions;
void AllocBoard(int *** Board, int Queens)
{
int i;
*Board = (int **)malloc(sizeof(int *) * Queens);
for(i = 0; i < Queens; i++)
{
(*Board)[i] = (int *)malloc(sizeof(int) * Queens);
memset((*Board)[i], 0, sizeof(int) * Queens);
}
}
void DeallocBoard(int *** Board, int Queens)
{
int i;
for(i = 0; i < Queens; i++)
free((*Board)[i]);
free(*Board);
}
void SavePosition(int *** Board, int Queens, int Col, int Row, int Inc)
{
int i, j;
for(i = 0; i < Queens; i++)
{
if((*Board)[Col][i] >= 0) (*Board)[Col][i] += Inc;
if((*Board)[i][Row] >= 0) (*Board)[i][Row] += Inc;
}
for(i = Col, j = Row; j < Queens && i < Queens; i++, j++)
if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
for(i = Col, j = Row; j >= 0 && i >= Col; i--, j--)
if((*Board)[i][j] >= 0) (*Board)[Col][j] += Inc;
for(i = Col, j = Row; j >= 0 && i < Queens; i++, j--)
if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
for(i = Col, j = Row; j < Queens && i >= Col; i--, j++)
if((*Board)[i][j] >= 0) (*Board)[i][j] += Inc;
}
void FindSolutions(int *** Board, int Queens, int Col)
{
int i, j;
for(i = 0; i < Queens; i++)
{
if((*Board)[Col][i] != 0) continue;
(*Board)[Col][i] = -1;
if(Col + 1 == Queens)
Solutions++;
else
{
SavePosition(Board, Queens, Col, i, 1);
FindSolutions(Board, Queens, Col + 1);
SavePosition(Board, Queens, Col, i, -1);
}
(*Board)[Col][i] = 0;
}
}
void main(int argc, char **argv)
{
int Queens, ** Board = NULL;
clock_t Start, End;
clrscr();
if(argc < 2)
Queens = 8;
else
Queens = atoi(argv[1]);
Solutions = 0;
Start = clock();
AllocBoard(&Board, Queens);
FindSolutions(&Board, Queens, 0);
DeallocBoard(&Board, Queens);
End = clock();
printf("Solutions %ld\n", Solutions);
printf("Estimated time: %f", (End - Start) / CLK_TCK);
getch();
}
Hope this helps
Asking "why it doesn't work" about short and simple programs is not very well. Try debug it yourself with any debugger or simply using printing in important places/on each step. Actually, C has no arrays, instead it has pointers. You can work with them very alike, that is why all you need is to change int board[4][4] to int **board and add one argument: int N(count of cells) and that's all. All your other code shouldn't be changed.
I am trying to create a program in C that, given the user's input of a character boarder for a shape, fills the shape in.
http://pastebin.com/aax1dt0b
#include <stdio.h>
#include "simpio.h"
#include "genlib.h"
#define size 100
bool initArray(bool a[size][size]);
bool getshape(bool a[size][size]); /* Gets the input of the boarder of the shape from the user */
void fill(int x, int y, bool a[size][size]); /* fills the shape */
void printarray(bool a[size][size]); /* prints the filled shape */
main()
{
int x, y;
char i;
bool a[size][size];
initArray(a);
getshape(a);
printf("Enter the coordinates of the point the shape should be filled.\n");
printf("x=n\n"); /* gets the coordinates of the array to begin the fill algorithm from */
x = GetInteger();
printf("y=\n");
y = GetInteger();
fill(x, y, a);
printarray(a);
printf("Scroll up to view your filled shape\n");
getchar();
}
bool initArray(bool a[size][size])
{
int i, j;
for (i = 0; i < 100; i++)
{
for (j = 0; j < 100; j++)
{
a[i][j] = FALSE;
}
}
}
bool getshape(bool a[size][size])
{
int i, j, k;
bool flag;
char ch;
ch = 1;
printf("Enter your shape. When you are finished, type 'E'. \n");
for (i = 0; i < 100; i++)
{
flag = TRUE;
for (j = 0; ch != 10; j++)
{
ch = getchar();
if (ch == 69)
{
return a;
}
if (ch != 32) a[i][j] = TRUE;
}
ch = 1;
}
}
void fill(int x, int y, bool a[size][size])
{
if (a[y][x] != TRUE) a[y][x] = TRUE;
if (a[y][x - 1] != TRUE) fill(x - 1, y, a);
if (a[y - 1][x] != TRUE) fill(x, y - 1, a);
if (a[y][x + 1] != TRUE) fill(x + 1, y, a);
if (a[y + 1][x] != TRUE) fill(x, y + 1, a);
}
void printarray(bool a[size][size])
{
int i, j;
printf("\n\n\n");
for (i = 0; i < 100; i++)
{
for (j = 0; j < 100; j++)
{
if (a[i][j] == FALSE) printf(" ");
if (a[i][j] == TRUE) printf("*");
}
printf("\n");
}
}
My program works for the most part, but when it prints the filled shape, it adds one additional character to each row. For example, if the user's input it
***
* *
***
Then the output will be
****
****
**** (one extra row then it should be)
whereas it should be
***
***
***
anyone know how I can fix this?
Although there are several potential problems in your code, I'm going to just identifying the problem of the 4th column *'s. In the code below, although you're checking ch!=10 in the for statement, the value of a[i][j] is getting assigned TRUE before terminating the loop. So you might want to do if(ch!=32 && ch!=10) a[i][j]=TRUE;.
flag=TRUE;
for(j=0;ch!=10;j++)
{
ch=getchar();
if(ch==69)
{
return a;
}
if(ch!=32) a[i][j]=TRUE;
}
ch=1;