Scheduling algorithms in C Shortest Remain Time Next - c

I am working on Shortest Remaining Time Next Scheduling, where I must check every 1 time unit to see if there is another job that has a shorter time remaining left, if equal keep the current process. For the input I use:
PID ArrivalTime Burst/ExecutionTime
1 0 6
2 3 2
3 5 1
4 9 7
5 10 5
6 12 3
7 14 4
8 16 5
9 17 7
10 19 2
and my output: (on the left is what I am getting, the right is what it should be):
PID WAIT TURNAROUND PID WAIT TURNAROUND
1 0 9 1 0 9
2 0 2 2 0 2
3 0 1 3 0 1
4 0 26 4 0 26
5 0 14 5 0 5
6 0 3 6 3 6
7 1 5 7 4 10
8 8 13 8 8 13
9 18 25 9 18 25
10 0 2 10 0 2
Average Wait: 2.7 Ave Turnaround 10.0 Average Wait: 3.3 Average Turnaround 9.9
I have not been able to narrow down where the problem is in the srtn function, All but 3 of my outputs are correct, which is even more confusing! Any help would be appreciated!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/types.h>
#define LINELEN 512
#define MAX_PROCESS 100
#define TIME_QUANTUM 1
typedef struct process
{
int ID;
int arrival_time;
int time_to_completion;
double wait_time;
double turn_around;
double time_wait;
int active;
}process;
void fcfs(struct process[MAX_PROCESS], int);
void sjf (struct process[MAX_PROCESS], int);
void srtn(struct process[MAX_PROCESS], int);
void rr (struct process[MAX_PROCESS], int);
void rrc(struct process[MAX_PROCESS], int);
void print_info(struct process[MAX_PROCESS], int);
void sort_by_time(struct process array[MAX_PROCESS], int num_valid_pid);
int main(int ac,char *av[])
{
int counter=0;
int p1=0, p2=0, p3=0;
process array[MAX_PROCESS];
while ( scanf("%d %d %d", &p1, &p2, &p3) != EOF ){//Get all the info available and put it in array of structs
array[counter].ID = p1;
array[counter].arrival_time = p2;
array[counter].time_to_completion = p3;
array[counter].active = 0;
counter++;
}
//fcfs(array, counter);
//sjf (array, counter);
srtn(array, counter);
/*rr (array, counter);
rrc(array, counter);*/
return 0;
}
void srtn(struct process array[MAX_PROCESS], int num_pid){
printf("Shortest Remaining Time Next\n");//for the output so we know what algorithm
//create an array of pids that are valid to search.
int num_valid_processes = 0, current_time=0, i,j, next_process, counter = 0, fin_pid = 0, keep_going=0;//declarations
process to_sort[MAX_PROCESS];
//we want to do this next loop for as many processes as we have, or num_pid
while(keep_going!=1){
//adds all the available processes to the to sort array to be sorted
//available means that it has arrived, which means it is <= current_time
//after it gets all the processes, it breaks out of the for loop
for(i=counter; i<num_pid; i++){
if(array[i].arrival_time<=current_time){
to_sort[num_valid_processes]=array[i];
num_valid_processes++;
counter++;
}
else
break;
}
//sort the to_sort array by the time_to_completion
sort_by_time(to_sort,num_valid_processes);
//set the wait time and turnaround time for the next process
next_process = to_sort[0].ID-1;
if(array[next_process].active==0){//the id hasn't had the wait time calculated yet
array[next_process].wait_time = current_time-array[next_process].arrival_time;
array[next_process].active=1;
array[next_process].time_wait = current_time;
}
if(array[next_process].time_to_completion <= TIME_QUANTUM){
array[next_process].turn_around = array[next_process].wait_time + (current_time-array[next_process].time_wait)+array[next_process].time_to_completion;
fin_pid++;
//delete the process we just worked on so we don't get duplicates.
num_valid_processes--;
for(i=0;i<num_valid_processes;i++){
to_sort[i]=to_sort[i+1];
}
}
else{
array[next_process].time_to_completion = array[next_process].time_to_completion - TIME_QUANTUM;
//to_sort[0].time_to_completion = to_sort[next_process].time_to_completion - TIME_QUANTUM;
}
current_time = current_time+TIME_QUANTUM;
if(fin_pid==num_pid)
keep_going=1;
}
print_info(array, num_pid);
}
void print_info(struct process array[MAX_PROCESS], int num_pid){
int i;
double tot_wait=0, tot_turn = 0;
printf("\x1b[04mPID\tWAIT\tTURNAROUND\n\x1b[24m");
for(i=0; i<num_pid; i++){
printf("%d\t%.0f\t%.0f\n", array[i].ID, array[i].wait_time, array[i].turn_around);
tot_wait=tot_wait+array[i].wait_time;
tot_turn = tot_turn +array[i].turn_around;
}
printf("Average Wait: %.1f Average Turnaround %.1f\n", tot_wait/num_pid, tot_turn/num_pid);
}
void sort_by_time(struct process array[MAX_PROCESS], int num_valid_pid)
{
int i,j;
for (i = 0; i < num_valid_pid; i++)
{
int min = i;
for (j = i+1; j < num_valid_pid; j++){
if (array[j].time_to_completion < array[min].time_to_completion)
min = j;
if (array[j].time_to_completion == array[min].time_to_completion){
if(array[j].ID<array[min].ID)
min = j;
}
}
process temp = array[i];
array[i] = array[min];
array[min] = temp;
}
}

The problem occurs at time 12 -- pid 6 shows up needing 3 seconds and pid 5 is running with 3 seconds left. How do you resolve the tie between processes that need the same remaining time? In favor of pid 6 gives you the result on the left and in favor of pid 5 gives you the result on the right. Given your weak problem definition, either could be correct.

Related

Rearrange Matrix using threads

I`m trying to do this program, that taking matrix 4X4, and then creating 4 threads, and in parallel inserting the 4X4 matrix into array of 16 integer, sorting like this. odd number will go to odd index, and even number to even index in the array.
2 1 10 9 4 ec`
for example
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
will looks something like this:
The arranged array:
2 1 10 9 4 3 12 11 6 5 14 13 8 7 16 15
Num 2 was found by thread 0
Num 1 was found by thread 2
Num 10 was found by thread 1
Num 9 was found by thread 3
Num 4 was found by thread 0
Num 3 was found by thread 2
Num 12 was found by thread 1
Num 11 was found by thread 3
Num 6 was found by thread 0
Num 5 was found by thread 2
Num 14 was found by thread 1
Num 13 was found by thread 3
Num 8 was found by thread 0
Num 7 was found by thread 2
Num 16 was found by thread 1
Num 15 was found by thread 3
Now I came up with this code, but for some reason I'm not using all the threads like in the sample. I mean in the sample there is thread 0 then 2 then 1 then 3 etc. very mixed. I'm from other hand getting thread 0, thread 0, thread 0, 3, 3 ,0,0 etc.
How can I fix this?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define MAX 4
#define MAX_THREAD 4
int i = 0;
int newmatrix[16];
int oldmatrix[MAX][MAX] =
{1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16};
int isUsed(int num)
{
for (int p = 0; p < 16; p++)
if (newmatrix[p] == num)
return 0;
return 1;
}
void *printHello(void *threadid)
{
int j, k;
long tid;
tid = (long)threadid;
while (i < 16)
{
sleep(0.01);
for (j = 0; j < 4; j++)
{
for (k = 0; k < 4; k++)
{
if (oldmatrix[j][k] % 2 == 0 && isUsed(oldmatrix[j][k]))
{
newmatrix[i] = oldmatrix[j][k];
printf("Num %d was found by thread %ld\n", oldmatrix[j][k], tid);
i++;
}
else if (isUsed(oldmatrix[j][k]))
{
newmatrix[i] = oldmatrix[j][k];
printf("Num %d was found by thread %ld\n", oldmatrix[j][k], tid);
i++;
}
}
}
}
if (tid == 1)
{
sleep(2);
printf("Hello There! thread %ld \n\n", tid);
for (int p = 0; p < 16; p++)
printf("%d ", newmatrix[p]);
}
pthread_exit(NULL);
}
int main(int argc, char const *argv[])
{
pthread_t threads[MAX_THREAD];
int rc;
long t;
for (t = 0; t < MAX_THREAD; t++)
{
rc = pthread_create(&threads[t], NULL, printHello, (void *)t);
if (rc)
{
printf("ERORR; return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
}
pthread_exit(NULL);
}

C in printing function mutex does not work properly

I am trying to give an id to threads and then I want to print each threads id that I have given, but there is a situation about mutex I guess, I think I am handling the critical section but it seems I could not.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
struct info{
int id;
int flag;
};
void *print_info(void* arg){
struct info *arg_struct = (struct info*) arg;
pthread_mutex_lock(&m);
printf("%d ", arg_struct->id);
pthread_mutex_unlock(&m);
pthread_exit(0);
}
int main(int argc, char *argv[])
{
int number = 10;
pthread_t tid[number];
for (int i = 0; i < number; ++i) {
int info[2];
info[0] = i;
info[1] = 0;
pthread_create(&tid[i], NULL, print_info, &info);
}
for (int i = 0; i < number; ++i) {
pthread_join(tid[i], NULL);
}
return 0;
}
Here is the output:
1 2 3 4 5 6 7 8 9 9
Each time I execute it differ but more or less the concept is the same is does not print some values and it prints some more than once.
But the expected output is this:
0 1 2 3 4 5 6 7 8 9
[or something not in order but each value is exactly printed once I guess]
Thanks
Giving each thread its own control data
As written, your code cannot guarantee the sequence of the output numbers — the order in which the threads execute depends on the o/s and the hardware. You can easily make sure that each ID is printed just once, by making sure that each thread has its own struct info to work with. Your existing code (a) type-puns an array with a structure, which is a bad idea (alk's comment), and (b) reuses the same space on the main program's stack so that by the time the threads are at work, it is feasible for the main loop to have changed the values stored.
This is what #rafix07 said in a comment. You claimed to have tried the fix without success. I have to conclude that your amended code didn't do what was necessary.
You need to use code more like this (which also prints a newline at the end of each run):
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
struct info
{
int id;
int flag;
};
static void *print_info(void *arg)
{
struct info *arg_struct = (struct info *)arg;
pthread_mutex_lock(&m);
printf("%d ", arg_struct->id);
pthread_mutex_unlock(&m);
pthread_exit(0);
}
int main(void)
{
int number = 10;
pthread_t tid[number];
struct info info[number];
for (int i = 0; i < number; ++i)
{
info[i].id = i;
info[i].flag = 0;
pthread_create(&tid[i], NULL, print_info, &info[i]);
}
for (int i = 0; i < number; ++i)
{
pthread_join(tid[i], NULL);
}
putchar('\n');
return 0;
}
When I ran it 10 times in a row, I got the outputs:
0 7 2 8 3 1 4 9 5 6
1 8 0 9 2 3 6 5 4 7
0 4 5 2 3 6 7 1 8 9
0 1 2 3 4 5 6 7 8 9
2 7 0 3 5 6 4 8 1 9
2 0 7 6 3 5 4 8 9 1
0 9 1 3 5 6 7 2 8 4
0 7 1 8 4 3 9 2 5 6
0 7 1 8 3 5 4 2 9 6
0 3 4 5 6 1 2 8 7 9
As you can see, each of the numbers 0..9 appears once in each line of output, but the sequence in which the threads execute is anything but determinate.
I'm not convinced that the mutex is buying you anything. All I/O functions such as printf() must behave as if they use flockfile() on entry and funlockfile() on return.
Tested on a MacBook Pro running macOS Mojave 10.14.6 (don't ask!) with GCC 9.2.0.
Guaranteeing sequence
A simple modification ensures the sequence — the main thread locks the mutex before launching a thread, and the thread unlocks it before exiting. However, this means there is no meaningful concurrency — you might as well write:
for (int i = 0; i < 10; i++)
printf("%d ", i);
putchar('\n');
This would avoid all the overhead of starting, running, and cleaning up after the threads.
The revised code simply moves one line from the print_info() function into main():
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
pthread_mutex_t m = PTHREAD_MUTEX_INITIALIZER;
struct info
{
int id;
int flag;
};
static void *print_info(void *arg)
{
struct info *arg_struct = (struct info *)arg;
printf("%d ", arg_struct->id);
pthread_mutex_unlock(&m);
pthread_exit(0);
}
int main(void)
{
int number = 10;
pthread_t tid[number];
struct info info[number];
for (int i = 0; i < number; ++i)
{
info[i].id = i;
info[i].flag = 0;
pthread_mutex_lock(&m);
pthread_create(&tid[i], NULL, print_info, &info[i]);
}
for (int i = 0; i < number; ++i)
{
pthread_join(tid[i], NULL);
}
putchar('\n');
return 0;
}
And the output:
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
0 1 2 3 4 5 6 7 8 9
It fails because you keep passing a pointer to what is effectively the same vector to the child threads, and promptly overwriting the contents in the main thread while the child threads are running.
You could equally well get an output of all 9s given a loaded system. Or even the numbers in reverse (only because I don't remmember there being a guarantee anywhere that threads will be scheduled in the same order as you create them). Or a very very strange number because if the child threads don't start running till the main thread starts the join, whatever 'arg' points to will be in the middle of the pthread_join call stack.
All the mutex protects you from is the threads outputting to stdout at the same time.
In passing, casting an array of ints to a struct of 2 ints is undefined behaviour, which is a whole other can of worms.

Why 2 is not smaller than 10 on Codeblocks?

I just worked to my final exam with simple codes; when I try to sorting strings, I face annoying error. Why 2 is not smaller than 10 on my CodeBlocks IDE but is smaller than 10 on real and onlinegdb.com?
This is the annoying code:
#include <string.h>
#include <stdio.h>
#define STR_SIZ 20
int main()
{
char strArr[][STR_SIZ] = {"abc", "hdas", "sdfasf", "kakldf", "caksl", "casd", "keam", "cznjcx", "mnxzv", "jkalkds"};
char minStr[STR_SIZ];
strcpy(minStr, strArr[0]);
int N = sizeof(strArr)/sizeof(minStr);
// int N = 10;
for(int x = 0; x < N-1; x++)
{
printf("%d", x);
strcpy(minStr,strArr[x]);
int j;
for(j=1+x; j < 10; j++)
{
printf("%4d\n", j);
int cmp = strcmp(strArr[j], minStr);
if(cmp < 0)
strcpy(minStr,strArr[j]);
}
char temp[STR_SIZ];
strcpy(temp,strArr[x]);
strcpy(strArr[x], minStr);
strcpy(strArr[j], temp);
}
return 0;
}
Output on onlinegdb.com:
0 1
2
3
4
5
6
7
8
9
1 2
3
4
5
6
7
8
9
2 3
4
5
6
7
8
9
3 4
5
6
7
8
9
4 5
6
7
8
9
5 6
7
8
9
6 7
8
9
7 8
9
8 9
Output on CodeBlocks:
0 1
2
3
4
5
6
7
8
9
1 2
3
4
5
6
7
8
9
2
PS: I just have used Codeblock in the morning and it was okey with executing.
strArr has 10 elements. At the end of your loop, you call strcpy(strArr[j], temp);. This will write to strArr[10], which is out of bounds and will overwrite some unknown memory. Anything can happen after that.
You should save the j value when you copy a string into minStr.
FYI, your code above prints this as your final string order with onlinegdb:
abc
caksl
caksl
caksl
caksl
casd
cznjcx
cznjcx
jkalkds
jkalkds
So I think you have other problems as well.
try this
#include <string.h>
#include <stdio.h>
#define STR_SIZ 20
int main()
{
char strArr[][STR_SIZ] = {"abc", "hdas", "sdfasf", "kakldf", "caksl", "casd", "keam", "cznjcx", "mnxzv", "jkalkds"};
strcpy(minStr, strArr[0]);
// Calculate the number of elements this way.
const int N = sizeof(strArr)/sizeof(strArr[0]);
// int N = 10;
for(int x = 0; x < N-1; x++)
{
printf("%d", x);
int j;
for(j=1+x; j < N; j++) // Use N here too!
{
printf("%4d\n", j);
int cmp = strcmp(strArr[j], strArr[x]);
if(cmp < 0)
{
// Do the swaps only when needed.
char temp[STR_SIZ];
strcpy(temp,strArr[x]);
strcpy(strArr[x], strArr[j]);
strcpy(strArr[j], temp);
}
}
}
// Verify result
for(int x = 0; x < N; x++) printf("%s\n", strArr[x]);
return 0;
}
I moved your swap into your if check and got rid of your minStr as it was not needed. Notice how I calculate the N size too. Honestly, you were close, but you needed to verify your output.

Alternative way to Pascal's triangle using user defined functions

#include <stdio.h>
#include <conio.h>
int fact(int x);
int coeff(int y);
int main(){
int n,i,j,k;
printf("\nENTER THE POWER:");
scanf("%d",&n);
for (i=0;i<=n;i++){
for(k=n;k>i;k--){
printf(" ");
}
printf("%4d",coeff(i));
printf("\n");
}
getch();
}
int fact(int x){
int a , f=1 ;
for (a=x;a>0;a--){
if(x==0){
return 1;
}
return f*=a;
}
}
int coeff(int y){
int m ;
for(m=0;m<=y;m++) {
return (fact(y))/(fact(m)*fact(y-m));
}
}
I am a newbee in C programming . I have recently started printing patterns using C . I did the above coding of Pascal's Triangle myself . But my code doesn't give the correct answer in the CODE BLOCKS editor . I know that there are solutions to this in websites . But I want to develop my own reasonings(though it is oddly long ) . But I'm unable to find the fault here . Would someone kindly help me ?
THANKS ...
The solution below consists of correcting the errors in code along with some improvements:
1) Use getchar from stdio.h instead of getch from the non-standardconio.h.
2) The coeff function does not need a for loop.
3) The fact function calculates the factorial completely and only then returns the value.
4) Another for loop included in the main to print all the coefficients of a power in one line.
#include <stdio.h>
int fact(int x);
int coeff(int n, int y);
int main(){
int n,i,j,k;
n = i = j = k = 0;
printf("\nENTER THE POWER:");
scanf("%d",&n);
for (i=0;i<=n;i++){
for(k=n;k>i;k--){
printf(" ");
}
for(j=0;j<=i;j++){
printf("%4d",coeff(i, j));
}
printf("\n");
}
getchar();
}
int fact(int x){
int a , f=1 ;
if(x==0){
return 1;
}
for (a=x;a>0;a--){
f*=a;
}
return f;
}
int coeff(int n, int y){
return (fact(n))/(fact(y)*fact(n-y));
}
Output:
a.exe
ENTER THE POWER:5
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
a.exe
ENTER THE POWER:6
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
a.exe
ENTER THE POWER:7
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1

Segmentation fault due to recursion

I'm writing a program that is to take a number between 1-10 and display all possible ways of arranging the numbers.
Ex
input: 3
output:
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
Whenever I input 9 or 10, the program gives a segmentation fault and dumps the core. I believe the issue is my recursive algorithm is being called too many times. Could someone help point out how I could limit the amount of recursive calls necessary? Here is my current code:
void rearange(int numbers[11], int index, int num, int fact) {
int temp = numbers[index];
numbers[index] = numbers[index-1];
numbers[index-1] = temp;
int i;
for (i = 1; i <= num; ++i) // print the current sequence
{
printf("%d ", numbers[i]);
}
printf("\n");
fact--; // decrement how many sequences remain
index--; // decrement our index in the array
if (index == 1) // if we're at the beginning of the array
index = num; // reset index to end of the array
if (fact > 0) // If we have more sequences remaining
rearange(numbers, index, num, fact); // Do it all again! :D
}
int main() {
int num, i; // our number and a counter
printf("Enter a number less than 10: ");
scanf("%d", &num); // get the number from the user
int numbers[11]; // create an array of appropriate size
// fill array
for (i = 1; i <= num; i++) { // fill the array from 1 to num
numbers[i] = i;
}
int fact = 1; // calculate the factorial to determine
for (i = 1; i <= num; ++i) // how many possible sequences
{
fact = fact * i;
}
rearange(numbers, num, num, fact); // begin rearranging by recursion
return 0;
}
9! (362880) and 10! (3628800) are huge numbers that overflow the call stack when you do as many recursive calls. Because all the local variables and formal parameters have to be stored. You either you have to increase the stack size or convert the recursion into iteration.
On linux, you can do:
ulimit -s unlimited
to set the stack size to unlimited. The default is usually 8MB.
Calculating permutations can be done iteratively, but even if you do it recursively there is no need to have a gigantic stack (like answers suggesting to increase your system stack say). In fact you only need a tiny amount of your stack. Consider this:
0 1 <- this needs **2** stackframes
1 0 and an for-loop of size 2 in each stackframe
0 1 2 <- this needs **3** stackframes
0 2 1 and an for-loop of size 3 in each stackframe
1 0 2
1 2 0
2 1 0
2 0 1
Permuting 9 elements takes 9 stackframes and a for-loop through 9 elements in each stackframe.
EDIT: I have taken the liberty to add a recursion-counter to your rearrange-function, it now prints like this:
Enter a number less than 10: 4
depth 1 1 2 4 3
depth 2 1 4 2 3
depth 3 4 1 2 3
depth 4 4 1 3 2
depth 5 4 3 1 2
depth 6 3 4 1 2
depth 7 3 4 2 1
depth 8 3 2 4 1
depth 9 2 3 4 1
depth 10 2 3 1 4
depth 11 2 1 3 4
depth 12 1 2 3 4
depth 13 1 2 4 3
depth 14 1 4 2 3
depth 15 4 1 2 3
depth 16 4 1 3 2 which is obviously wrong even if you do it recursively.
depth 17 4 3 1 2
depth 18 3 4 1 2
depth 19 3 4 2 1
depth 20 3 2 4 1
depth 21 2 3 4 1
depth 22 2 3 1 4
depth 23 2 1 3 4
depth 24 1 2 3 4
....
The recursion-leafs should be the only ones which output so the depth should be constant and small (equal to the number you enter).
EDIT 2:
Ok, wrote the code. Try it out:
#include "stdio.h"
void betterRecursion(int depth, int elems, int* temp) {
if(depth==elems) {
int j=0;for(;j<elems;++j){
printf("%i ", temp[j]);
}
printf(" (at recursion depth %u)\n", depth);
} else {
int i=0;for(;i<elems;++i){
temp[depth] = i;
betterRecursion(depth+1, elems, temp);
}
}
}
int main() {
int temp[100];
betterRecursion(0, 11, temp); // arrange the 11 elements 0...10
return 0;
}
I'd make your rearange function iterative - do while added, and recursive call removed:
void rearange(int numbers[11], int index, int num, int fact) {
int temp;
do
{
temp = numbers[index];
numbers[index] = numbers[index-1];
numbers[index-1] = temp;
int i;
for (i = 1; i <= num; ++i) // print the current sequence
{
printf("%d ", numbers[i]);
}
printf("\n");
fact--; // decrement how many sequences remain
index--; // decrement our index in the array
if (index == 1) // if we're at the beginning of the array
index = num; // reset index to end of the array
} while (fact > 0);
}
This is not a task for a deep recursion.
Try to invent some more stack-friendly algorithm.
Following code has rather troubles with speed than with stack size...
It's a bit slow e.g. for n=1000 but it works.
#include <stdio.h>
void print_arrangement(int n, int* x)
{
int i;
for(i = 0; i < n; i++)
{
printf("%s%d", i ? " " : "", x[i]);
}
printf("\n");
}
void generate_arrangements(int n, int k, int* x)
{
int i;
int j;
int found;
if (n == k)
{
print_arrangement(n, x);
}
else
{
for(i = 1; i <= n; i++)
{
found = 0;
for(j = 0; j < k; j++)
{
if (x[j] == i)
{
found = 1;
}
}
if (!found)
{
x[k] = i;
generate_arrangements(n, k + 1, x);
}
}
}
}
int main(int argc, char **argv)
{
int x[50];
generate_arrangements(50, 0, x);
}
Your program is using too many recursions unnecessarily. It is using n! recursions when actually n would be enough.
To use only n recursions, consider this logic for the recursive function:
It receives an array nums[] of n unique numbers to arrange
The arrangements can have n different first number in them, as there are n different numbers in the array
(key step) Loop over the elements of nums[], and in each iteration create a new array but with the current element removed, and recurse into the same function passing this shorter array as parameter
As you recurse deeper, the parameter array will be smaller and smaller
When there is only one element left, that's the end of the recursion
Using this algorithm, your recursion will not be deeper than n and you will not get segmentation fault. The key is in the key step, where you build a new array of numbers that is always 1 item shorter than the input array.
As a side note, make sure to check the output of your program before you submit, for example run it through | sort | uniq | wc -l to make sure you are getting the correct number of combinations, and check that there are no duplicates with | sort | uniq -d (the output should be empty if no dups).
Spoiler alert: here's my implementation in C++ using a variation of the above algorithm:
https://gist.github.com/janosgyerik/5063197

Resources