C program doesn't start, implementing Dijkstras algorithm - c

I am doing an assignment for class that is supposed to be coded a very specific way. Here is the goal:
Goal: To implement Dijkstra’s algorithm for single source shortest path problem
for a given directed graph using an adjacency matrix representation of the
graph.
I am using Makefile to compile the code. Input will be taken via the terminal/console ./a7 < datafile. Here is an example of the input:
6 11 0
0 1 50
0 2 10
0 4 45
1 2 15
1 4 10
2 0 20
2 3 15
3 1 20
3 4 35
4 3 30
5 4 03
And the expected output:
0 2 10
0 3 25
0 1 45
0 4 45
0 5 INF (no path)
Here is the code:
#include <limits.h> /* for INT_MAX */
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#define N 10 /* max matrix size is 10 x 10 */
#define INF INT_MAX /* infinity? */
int main(int argc, char **argv) {
void getdata(int amtrx[][N], int *sz, int *stv);
void dijkstras(int amtrx[][N], int src);
if (argc < 2) {
printf("Missing Filename.\n");
return(1);
} else if (argc > 2) {
printf("Too many arguments.\n");
return(1);
}
FILE *f = fopen(argv[1], "r");
int amtrx[N][N], *sz, *stv;
stv = malloc(sizeof(int));
sz = malloc(sizeof(int));
getdata(amtrx, sz, stv);
dijkstras(amtrx, *stv);
fclose(f);
return(0);
}
void getdata(int amtrx[][N], int *sz, int *stv) {
int i, j, nsz, nedg, fr, to, vtx, wt;
scanf("%d %d %d", &nsz, &nedg, &vtx);
for(i = 0; i < nsz; i++)
for(j = 0; j < nsz; j++)
amtrx[i][j] = INF;
for(i = 0; i < nedg; i++) {
scanf("%d %d %d", &fr, &to, &wt);
amtrx[fr][to] = wt;
amtrx[to][fr] = wt;
}
*sz = nsz;
*stv = vtx;
}
void dijkstras(int amtrx[][N], int src) {
void printpaths(int amtrx[][N]);
int mindistance(int dist[], bool sptSet[]);
int dist[N];
bool sptSet[N];
int i, count, v, u;
for (i = 0; i < N; i++)
dist[i] = INF, sptSet[i] = false;
dist[src] = 0;
for (count = 0; count < N - 1; count++) {
u = mindistance(dist, sptSet);
sptSet[u] = true;
for (v = 0; v < N; v++)
if (!sptSet[v] && amtrx[u][v] && dist[u] != INF && dist[u] + amtrx[u][v] < dist[v]) {
dist[v] = dist[u] + amtrx[u][v];
}
}
printpaths(amtrx);
}
int mindistance(int dist[], bool sptSet[]) {
int min = INF, min_index;
int v;
for (v = 0; v < N; v++)
if (sptSet[v] == false && dist[v] <= min)
min = dist[v], min_index = v;
return min_index;
}
void printpaths(int amtrx[N][N]) {
//to be written
}
So far it just runs forever and doesn't print anything. I suspect maybe an infinite loop but I can't see where it's happening. I tried to run in GDB and it just says Starting program: /a7 datafile and goes no where. I also would like help making sure my algorithm is correct, but I can save that for another question if need be. Thanks in advance!

To find out what is wrong with help of gdb you usually need to run program in step mode to see where and why it hangs or loops.
Ensure that you compiled your program with debug symbols (if you are using gcc or similar compiler then -g option is needed).
To avoid going over whole program in step mode you can just hit Ctrl-C in gdb at the time you think your program hanged and then enter command bt. It will show you where your program is. You can then enter command cont, and break program execution after some time to see if you are in different place, or in the same...
If you still don't know what is the reason of your problem after step 2, you can kill program and set up break point before the place you have identified as being the one in which your program hangs/loops --- read gdb documentation about break to see how to set up breakpoint.
Here is link for gdb tutorial hosted at CMU: https://www.cs.cmu.edu/~gilpin/tutorial/

Related

Find minimum number of wires to connect the bulbs code

I have written this C code to find a minimum number of wires required to switch on all the bulbs.
The problem is that there is x number of computers, some of which are On and some are Off and the distance between these bulb from the first bulb is given. The computer can be switched ON by connecting it to its nearby ON the bulb.
So the inputs are as follows:
X = 6 (number of bulbs)
1 0 1 1 0 1(1 means the bulb is ON and 0 means the bulb is OFF)
2 4 8 36 37 40 (distance between one bulb from the first bulb)
and the output will be:
3 (Reason: 4 - 2 = 2, 37 - 36 = 1, 2 + 1 = 3)
#include <stdio.h>
int main(){
int n,pre,post,sum = 0;
scanf("%d",&n);
int arr[n],dist[n];
for(int i =0;i<n;i++){
scanf("%d ",&arr[i]);
}
for(int i =0;i<n;i++){
scanf("%d ",&dist[i]);
}
for(int i =0;i<6;i++){
if(arr[i] == 0){
pre = dist[i]-dist[i-1];
post = dist[i+1]-dist[i];
if(pre>post){
sum +=post;
}
else{
sum+=pre;
}
}
}
printf("\n %d",sum);
}
It keeps on taking the inputs. Please tell me what is the error in this code?
Thanks in advance.
Edited: I missed that scanf("%d",n) by mistake. It was there in my original code and the problem still persists.
As Sandrin mentioned, n is not defined.
Assuming your input file is:
6
1 0 1 1 0 1
2 4 8 36 37 40
You need to add code to set n:
scanf("%d ",&n);
And, you need to insert this before the definitions of your matrix
Here's the refactored code:
#include <stdio.h>
int
main(void)
{
int n, pre, post, sum = 0;
#if 1
scanf("%d ",&n);
#endif
int arr[n], dist[n];
for (int i = 0; i < n; i++)
scanf("%d ", &arr[i]);
for (int i = 0; i < n; i++)
scanf("%d ", &dist[i]);
for (int i = 0; i < 6; i++) {
if (arr[i] == 0) {
pre = dist[i] - dist[i - 1];
post = dist[i + 1] - dist[i];
if (pre > post) {
sum += post;
}
else {
sum += pre;
}
}
}
printf("\n %d", sum);
return 0;
}
Putting a side technical errors (e.g. n not initialized), the algorithms assumes that all problems can be solved by single pass. This is not true for cases like:
1 0 0 0 0 1
0 1 3 4 6 7
Where the code will choose to connect bulbs [0,1], [2,3], and [4,5], based on pre/post distances. However, bulbs 2 and 3 will remain disconnected.
A better algorithm will attempt to find, for each sequence of off bulbs, which is the most expensive connection, and avoid it.
I have come up with this solution for my code and I have tried to consider all the test cases. If you find any test case that won't run feel free to tell.
#include <stdio.h>
#include <stdlib.h>
int main(int ac, char **av){
int n,pre,post,sum = 0;
scanf("%d",&n);
int *input,*distance;
input = malloc(n * sizeof(int));
for (int i=0; i < n; i++)
{
scanf("%d", &input[i]);
}
distance = malloc(n * sizeof(int));
for (int i=0; i < n; i++)
{
scanf("%d", &distance[i]);
}
for(int i =0;i<6;i++){
if(input[i] == 0){
pre = distance[i]-distance[i-1];
if(input[i+1]==1){
post = distance[i+1]-distance[i];
input[i] =1;
if(pre>post){
sum +=post;
}
else{
sum+=pre;
}
}
else{
sum = sum+pre;
}
printf("%d.....%d....%d\n",pre,post,sum); //Debugging
}
}
printf("\n %d",sum);
free(input);
free(distance);
}

C Insertion Sort Program Fails With Many Inputs

Heyo!
I'm new to C and have hit a brick wall trying to sort a set of numbers.
If I input '5 3 0 9 5', it will correctly return 9 5 5 3 0.
However, '5 3 0 0 9 9 10 11 13 14 9' doesn't return a thing. Some debugging shows it gets to the 3, then just stops.
Where should I start looking?
Here's my code, but general suggestions are fine:
#include <stdio.h>
#include <stdlib.h>
int getvals(int A[]);
void val_swap(int *a,int *b);
int main() {
int len = 0;
int vals[len];
len = getvals(vals);
int i = 0, j = 0;
/* Search through the values from start to finish */
for (; i < len; i++) {
/* Search back through the values, right to left. If we find a smaller value, swap. */
for (j = i-1; j >= 0 && vals[j+1] > vals[j]; j--) {
/* Swap */
val_swap(&vals[j], &vals[j+1]);
}
}
/* Print the sorted array */
int k = 0;
for (; k < len; k++) {
printf("%d ", vals[k]);
}
return 0;
}
int getvals(int A[]) {
/* Gets a list of integer values from the user */
int num, arr_len = 0;
printf("Enter numbers. CTRL + D to end: ");
while(scanf("%d", &num)) {
A[arr_len] = num;
arr_len++;
}
return arr_len;
}
void val_swap(int *a, int *b) {
int tmp;
/* Save the value of b to temp var */
tmp = *b;
/* Swap the pointer values */
*b = *a;
/* Reassign value */
*a = tmp;
}
Maybe the returned value of getvals is less than the amount of '5 3 0 0 9 9 10 11 13 14 9' , so many data.
But I am wondering whether it can pass the compilation, int vals[len], when len is 0, we don't say whether this is right, but the size of vals has already fixxed because the space of vals is in stack, no heap's.
So in my opinion, there are no enough spaces to run the program.

Printing a Diamond of Numbers in C

int print_pattern(){
int x;
int y;
int i;
//for loop for the bottom and the top, 0 is the top and 1 is the bottom while it stops at anything above 2.
for (i = 0; i<2;i++){
//loop to the current number
for (x=1;x<=input;x+=2){
// top or bottom, this is the top because i had made the top of the diamond the 0
// therefore this makes my diamond print the top of the function.
if ( i == 0){
//starts for the top of the diamond. and counts the spaces.
for (y=1; y<=input-x; y++){
printf(" ");
}
//starts the printing of the diamond.
for (y=1; y<2*x;y++){
printf("%d ", y);
}
}
//bottom of the diamond, which is from the 1. For this spot it take in the one from the for loop to
// this if statement.
if (i==1){
//counting spaces again
for(y = 1; y<=x; y++){
printf(" ");
}
//printing again but this is the bottom of the pyramid. #really need to comment more
for(y = 1; y<(input-x)*2;y++){
printf("%d ", y);
}
}
//next line starts when printing out the numbers in the output.
printf("\n");
}
}
}
The output is supposed to look like a diamond of the numbers ending with the odd numberat each row. but it is going +2 number past the input and then also not printing the last line. Which should have a single one.
1 1
1 2 3 1 2 3 4 5
1 2 3 4 5 1 2 3 4 5 6 7 8 9
1 2 3 1 2 3 4 5 6 7
1 1 2 3
The left is what is expected and the right is what I currently am getting when inputting 5.
Because you already increment x by 2 in the upper part, you don't need to let the print loop run to y<2*x. It should probably just run to x.
The print loop in the lower part suffers from the fact that y<(input-x)*2 should probably be y<input-x*2 (you want to print 2 less each time).
Generally I'd try to name variables in a more speaking way, like printStartPosition, maxNumToPrint, stuff like that. That makes it easier by a surprising margin to understand a program.
As an enhancement, the two code blocks depending on the i value inside the x loop are structurally very similar. One could try to exploit that and collapse both of them into a function which gets a boolean parameter like "ascending", which increments y when true and decrements it when false. Whether that improves or hinders readability would have to be seen.
Also, keep your variables local if possible.
Peter Schneider has already raised some valid points in his answer.
Think about what you have to do when you print a diamond of height 5:
print 1 centered;
print 1 2 3 centered;
print 1 2 3 4 5 centered;
print 1 2 3 centered;
print 1 centered.
Sou you could write a function that prints the numbers from 1 to n centered in a line and call it with n = 1, 3, 5, 3, 1. This can be achieved with two independent loops, one incrementing n by 2, the other decrementing it.
Another approach is to recurse: print the lines as you go deeper, incrementing n by 2 until you reach the target width, at which point you don't recurse, but return and print lines with the same parameters again as you go up. This will print each line twice except the middle one.
Here's a recursive solution:
#include <stdlib.h>
#include <stdio.h>
void print_line(int i, int n)
{
int j;
for (j = i; j < n; j++) putchar(' ');
for (j = 0; j < i; j++) printf("%d ", (j + 1) % 10);
putchar('\n');
}
void print_pattern_r(int i, int n)
{
print_line(i, n); // print top as you go deeper
if (i < n) {
print_pattern_r(i + 2, n); // go deeper
print_line(i, n); // print bottom as you return
}
}
void print_pattern(int n)
{
if (n % 2 == 0) n++; // enforce odd number
print_pattern_r(1, n); // call recursive corefunction
}
int main(int argc, char **argv)
{
int n = 0;
if (argc > 1) n = atoi(argv[1]); // read height from args, if any
if (n <= 0) n = 5; // default: 5
print_pattern(n);
return 0;
}
A JAVA STAR PATTERN PROGRAM FOR DIAMOND SHAPE converted to C Program. Code comment will explain the changes and flow.
#include <stdio.h>
#include <string.h>
void myprintf(const char* a) {
static int iCount = 0;
if (strcmp(a, "\n") == 0) {
iCount = 0; //if it is new line than reset the iCount
printf("\n"); //And print new line
} else
printf(" %d", ++iCount); //Print the value
}
void main() {
int i, j, m;
int num = 5; //Enter odd number
for (i = 1; i <= num; i += 2) { //+=2 to skip even row generation
for (j = num; j >= i; j--)
printf(" ");
for (m = 1; m <= i; m++)
myprintf(" *"); //display of star converted to number
myprintf("\n");
}
num -= 2; //Skip to generate the middle row twice
for (i = 1; i <= num; i += 2) { //+=2 to skip even row generation
printf(" ");
for (j = 1; j <= i; j++)
printf(" ");
for (m = num; m >= i; m--)
myprintf(" *"); //display of star converted to number
myprintf("\n");
}
}
Output:
1
1 2 3
1 2 3 4 5
1 2 3
1
Here's the short code for such a diamond.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int w = 9;
int l;
for(l=0; l < w; ++l)
{
printf("%*.*s\n", abs(w/2 - l)+abs((2*l+1)-(2*l+1>w)*2*w), abs((2*l+1)-(2*l+1>w)*2*w), "123456789");
}
return 0;
}

Preventing repetition of same number that created randomly

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
int i,j,z,w,c; /* counter*/
int ticket[6],n[6];
int a; /*numbers of one ticket*/
int x; /* Random numbers of tickets*/
int num; /*Quantity of tickets*/
int loser = 0; /*initialize the number of known-tickets*/
int threeknown = 0;
int fourknown = 0;
int fiveknown = 0;
int winner = 0;
srand (time(NULL));
printf ("Please enter the lucky ticket numbers between 0 and 50\n");
for (i=0;i<6;i++) { /* loop for entering numbers of ticket from keyboard*/
scanf ( "%d",&a);
if (a<50 && a>0){
ticket[i] = a;
}
else {
printf ("\a ERROR: Please enter number between 0 and 50\n");
i--; /* enter again */
}
}
printf ("Lucky ticket is:\n");
for (i=0;i<6;i++) {
printf ("%3d",ticket[i]);
}
printf ("\n");
printf ("Please enter the quantity of tickets\n\a");
scanf ("%d",&num);
for (z=0;z<num;z++) { /* For each ticket */
for (j=1;j<=6;j++) {
x = 1 + rand()%49;
n[j] = x;
printf ("%3d",n[j]);
}
printf("\n\n");
}
for (z=0;z<num;z++){ /*counter for each ticket control */
if (ticket[0]==n[0] && ticket[1]==n[1] && ticket[2]==n[2] && ticket[3]==n[3] && ticket[4]==n[4] && ticket[5]==n[5]) {
winner += 1;
}
if (ticket[0]==n[0] && ticket[1]==n[1] && ticket[2]==n[2] && ticket[3]==n[3] && ticket[4]==n[4]) {
fiveknown += 1;
}
if (ticket[0]==n[0] && ticket[1]==n[1] && ticket[2]==n[2] && ticket[3]==n[3]) {
fourknown += 1;
}
if (ticket[0]==n[0] && ticket[1]==n[1] && ticket[2]==n[2]) {
threeknown += 1;
}
else {
loser += 1;
}
}
printf ("Number of winners : %d\n",winner);
printf ("Number of five-knowns : %d\n",fiveknown);
printf ("Number of four-knowns : %d\n",fourknown);
printf ("Number of three-knowns : %d\n",threeknown);
printf ("Number of losers : %d\n",loser);
system ("PAUSE");
return 0;
}
I have project about C coding Bingo Program. I need to maintain a winner ticket from keyboard between 0 and 50 (12 34 23 11 47 4) and then I need to generate tickets randomly. In these tickets none of them have the same number and the sorting is not important. For example ( 23 12 10 4 9 46 ). My question is to how to have these kind of tickets ? I don't want to have this kind of tickets ( 12 43 20 12 9 4 )
Build an array of the fifty acceptable values, choose one, and then remove it from the array.
Since the order in the array is not important, you can remove it at little cost by overwriting it with the last value and decreasing the "array count" variable.
void RemoveFromArray(int* arr, size_t *pNumberOfElements, size_t indexToRemove)
{
//Note: I'm not putting the error/bounds checking because it's not what the question is about.
size_t indexLast = *pNumberOfElements - 1;
arr[indexToRemove] = arr[indexLast];
(*pNumberOfElements)--;
}
void ChooseRandom6of50(int* random6ints)
{
int arr[50];
size_t nElements = 50;
{
size_t i;
for(i=0 ; i<50 ; i++)
arr[i] = (int)(i+1); //Fill with values 1 to 50
}
{
size_t iDest;
for(iDest=0 ; iDest<6 ; iDest++)
{
int rnd = rand() % nElements; //The real code should use the more elaborate random formula
size_t randIndex = rnd;
random6ints[iDest] = arr[randIndex];
RemoveFromArray(arr, &nElements, randIndex);
}
}
}
For a small number of tickets picked, the easiest way is to draw tickets randomly as you did already, but draw again if the ticket is already in the lot of drawn ticktes until you have a new ticket:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX
int contains(int ticket[], int n, int which)
{
while (n-- > 0) {
if (ticket[n] == which) return 1;
}
return 0;
}
void draw(int ticket[], int n, int m)
{
int i, t;
if (n > m) return;
for (i = 0; i < n; i++) {
do {
t = rand() % m;
} while (contains(ticket, i, t));
ticket[i] = t;
}
}
int main (void)
{
int ticket[6];
int i;
draw(ticket, 6, 50);
for (i = 0; i < 6; i++) printf("%4d", ticket[i]);
printf("\n");
return 0;
}
Note that the draw function does not do anything if the number of tickets to draw, n, is bigger than the tickets available, m, because that would lead to an infinite loop. If n == m the draw is like shuffling, albeit in a very inefficient way. (The draw function should probably return an error code or abort the program in that case, but in oder to keep things simple, I've left that out.)
The contains function should also come in handy if you want to compare the user's tickets with the draw. (Also, it would look more like programming if you could turn your variable threeknown, fiveknown and so on into an array hits[7].)

BSP implementation Sieve Of Erastothenes doesn't print C

I'm working on implementing a parallel algorithm of the Sieve Of Erastothenes in C using BSP.
My code compiles and executes but doesn't print the primes.
When I do ./bspsieve 2 1000 for example the only output I get is
"It took : 0.000371 seconds for proc 0 out of 2." while it should be printing all the found primes!
Oddly enough the algorithm does work it seems like. If I use a larger upperbound in the above example, it takes longer. When I assign more processors, it takes less time. So probably a stupid mistake somewhere, but I have serious problems with C and am working on a remote computer so unsure of that tools I've got...
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <mcbsp.h>
/*
Note: To compile, this file has to be in the same folder as mcbsp.h and you need the 2 following commands:
gcc -Iinclude/ -pthread -c -o bspsieve.o bspsieve.c
gcc -o bspsieve bspsieve.o lib/libmcbsp1.1.0.a -lpthread -lrt
*/
int procs;
int upperbound;
int *primes;
//SPMD function
void bspSieve(){
bsp_begin(procs);
int p = bsp_nprocs(); // p = number of procs obtained
int s = bsp_pid(); // s = proc number
float blocksize; // block size to be used, note last proc has a different size!
if( s != p-1){
blocksize = ceil(upperbound/p);
} else {
blocksize = upperbound - (p-1)*ceil(upperbound/p);
}
// Initialize start time and end time, set start time to now.
double start_time,end_time;
start_time = bsp_time();
// Create vector that has block of candidates
int *blockvector;
blockvector = (int *)malloc(blocksize*sizeof(int));
int q;
for(q = 0; q<blocksize; q++){
//List contains the integers from s*blocksize till blocksize + s*blocksize
blockvector[q] = q + s*blocksize;
}
//We neglect the first 2 'primes' in processor 0.
if(s == 0){
blockvector[0] = 0;
blockvector[1] = 0;
}
// We are using the block distribution. We assume that n is large enough to
// assure that n/p is larger than sqrt(n). This means that we will always find the
// sieving prime in the first block, and so have to broadcast from the first
// processor to the others.
long sieving_prime;
int i;
bsp_push_reg( &sieving_prime,sizeof(long) );
bsp_sync();
for(i = 2; i * i < upperbound; i++) {
//Part 1: if first processor, get the newest sieving prime, broadcast. Search for newest prime starting from i.
if(s == 0){
int findPrimeNb;
for(findPrimeNb = i; findPrimeNb < blocksize; findPrimeNb++) {
if( blockvector[findPrimeNb] != 0) {
sieving_prime = blockvector[findPrimeNb];
//broadcast
int procNb;
for(procNb = 0; procNb < p; ++procNb){
bsp_put(procNb, &sieving_prime,&sieving_prime,0,sizeof(long));
}
break;
}
}
}
bsp_sync();
//Part 2: Sieve using the sieving prime
int sievingNb;
for(sievingNb = 0; sievingNb < blocksize; sievingNb++){
//check if element is multiple of sieving prime, if so, pcross out (put to zero)
if( blockvector[sievingNb] % sieving_prime == 0){
blockvector[sievingNb] = 0;
}
}
}
//part 3: get local primes to central area
int transferNb;
long transferPrime;
for(transferNb = 0; transferNb < blocksize; transferNb++){
transferPrime = blockvector[transferNb];
primes[transferPrime] = transferPrime;
}
// take the end time.
end_time = bsp_time();
//Print amount of taken time, only processor 0 has to do this.
if( s == 0 ){
printf("It took : %.6lf seconds for proc %d out of %d. \n", end_time-start_time, bsp_pid(), bsp_nprocs());
fflush(stdout);
}
bsp_pop_reg(&sieving_prime);
bsp_end();
}
int main(int argc, char **argv){
if(argc != 3) {
printf( "Usage: %s <proc count> <upper bound> <n", argv[ 0 ] );
exit(1);
}
//retrieve parameters
procs = atoi( argv[ 1 ] );
upperbound = atoi( argv[ 2 ] );
primes = (int *)malloc(upperbound*sizeof(int));
// init and call parallel part
bsp_init(bspSieve, argc, argv);
bspSieve();
//Print all non zeros of candidates, these are the primes.
// Primes only go to p*p <= n
int i;
for(i = 0; i*i <= upperbound; i++) {
if(primes[i] > 0) {
printf("%d, ",primes[i]);
}
}
return 0;
}
printf doesn't automatically include a trailing newline, and it doesn't generally flush the output buffer until it outputs a newline; so probably you just need to add a
printf("\n");
at the end of your program, just before your return 0;.
Alternatively, or additionally, if you want to see the output as-you-go (if BSP allows that), you can add a
fflush(stdout);
right after your printf("%d, ",primes[i]);, to explicitly flush the output buffer.

Resources