Parallelization of Combination - c

I have got a piece of code that prints the combination of M number From N (nCm);
As it is a recursion, it works very slow when N is large.
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define M 4
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d\n", queue[i]);
}
}
queue[top++] = input[s];
comb(input,s+1, n, M);
top--;
comb(input,s+1, n, M);
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombination():\n");
comb(array,0, N, M);
printf("\n");
}
I would like to know if there is any space for improvement in the algorithm above?
if possible, can I use openMP ?
Thanks

To me your code was even giving the desired output. see
I have changed
printing format each combination was not good enough.
repeated combinations. (note: else part of if statement added).
reduced 2 recursive call with a loop and a recursive call. (Less space.)
The required code is:
#include <stdio.h>
#include <stdlib.h>
#define N 20
#define M 6
int result[M]= {0}; // THE ARRAY THAT SAVE THE RESULT OF ONE COMBINATION
int queue[N] = {0};
int top = 0;
void comb(int* input,int s, int n, int m)
{
if (s > n)
return ;
if (top == m)
{
printf("\n");
for (int i = 0; i < m; i++)
{
result[i] = queue[i];
printf("%d ", queue[i]);
}
}else{
for(int ss=s;ss<n;ss++){
queue[top++] = input[ss];
comb(input,ss+1, n, m);
top--;
}
//comb(input,s+1, n, m);
}
}
int main()
{
int array[] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,
27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,
50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,
73,74,75,76,77,78,79,80};
printf("\ncombinations():\n");
comb(array,0, N, M);
printf("\n");
}

Related

I want 2 for loop -> 1 for loop C

I am solving algorithm problem.
It is elements in array, pair -> one value;
I input array's size and add value.
i solve this problem but i meet time complexity problem at biggggg number - n
how can i solve this time complexity problem?
i try to solve one for loop but can't well
plz help me
#include <stdio.h>
int main(void){
int n,m,i,j;
int count=0;
scanf("%d %d",&n, &m);
int array[n];
for(i=0;i<n;i++){
scanf("%d",&array[i]);
}
for(i=0;i<n;i++){
for(j=i;j<n;j++){
if(m==array[i]+array[j]){
count++;
}}
}
printf("%d",count);
return 0;
}
Here is a simple two-pointer technique, after sorting.
It will work as it is because there is no duplicate.
In practice, two indices are used, one from the start of the array, one from the end of the array. We increase the first or decrease the second one, depending on the value of the sum.
Complexity: O(n logn) for sorting, and O(n) for the second step.
#include <stdio.h>
#include <stdlib.h>
int compare_ints(const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
int count_sum (int* A, int n, int target) {
int count = 0;
qsort(A, n, sizeof(int), compare_ints);
int left = 0;
int right = n-1;
while (left < right) {
int sum = A[left] + A[right];
if (sum == target) {
count++;
left++;
right--;
} else if (sum < target) {
left++;
} else {
right--;
}
}
return count;
}
int main() {
int A[] = {8, 2, 7, 5, 3, 1};
int target = 10;
int n = sizeof(A)/sizeof(A[0]);
int ans = count_sum (A, n, target);
printf ("count = %d\n", ans);
return 0;
}

Can't figure out how to change my code to solve a recursive problem

Print k-element subsets of an n element set (In essence n choose k)
represent each subset as an array and skip B[0].
For example [0 1 0 1] means {1,3} to print.
I believe my main problem is in my printSubsets() function because I am calling the method twice.
But it looks like it can't do that; it ignores the "2" in the index until the very end of the program.
Code
#include <stdio.h>
#include <stdlib.h>
void printSet(int B[], int n) {
for(int j = 1; j <= n; j++) {
printf("%d", B[j]);
}
}
void printSubsets(int B[], int n, int k, int i) {
if(i <= n) {
if(k == 0) {
printSet(B, n);
printf("\n");
}else{
B[i] = 1; //print 1 in the index of interest and recurse
printSubsets(B, n, k-1, i++);
B[i] = 2; //print 2 as a holder to ignore that index
printSubsets(B, n, k, i++);
}
}
}
int main(){
int n;
int k;
scanf("%d %d", &n, &k);
int B[101];
printSubsets(B, n, k, 1);
return EXIT_SUCCESS;
}

min heap program stopped working

I am doing a simple minheap program but when size of heap is 4 i get an error program stopped working.
i checked heap size 2,3,5,6,7 program is working fine.
Why am i getting this error only when heapsize is 4?
I am using codeblocks 16.01, windows 10, gcc compiler.
minHeap.c
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
void MinHeapfy(int A[], int i, int N)
{
int l,r,temp,smallest;
l = 2*i;
r = 2*i + 1;
if((l<=N) && (A[l]<A[i]))
{
smallest = l;
}
else
{
smallest = i;
}
if((r<=N) && (A[r]<A[smallest]))
{
smallest = r;
}
if(smallest != i)
{
temp = A[smallest];
A[smallest] = A[i];
A[i] = temp;
MinHeapfy(A,smallest,N);
}
}
void BuildHeap(int A[],int N)
{
int i;
int f = floor(N/2);
printf("f %d", f);
for(i=f;i>=1;i--)
{
printf("i %d\n",i);
MinHeapfy(A,i,N);
}
}
int main()
{
int *A,N,T,data,q,i=1;
scanf("%d",&N);
A = (int *)calloc(N,sizeof(int));
for(i=1;i<=N;i++)
{
scanf("%d",&data);
A[i]=data;
}
BuildHeap(A,N);
for(i=1;i<=N;i++)
{
printf("%d ",A[i]);
}
return 0;
}
I can share some things that I learned till now:
void BuildHeap(int *A, int N);
void MinHeapfy(int *A, int i, int N);
In this 2 functions you just send a pointer not an array(difference between int *A and int A[5])
int main()
{
/*here it is better for you to declare like this
to see more easier which is which pointer and variable
(PS: at the moment you don't use q)*/
int N,T,data,i;//,q
int *A;
scanf("%d",&N);
A = (int *)calloc(N,sizeof(int));
for(i=0;i<N;i++)
{
scanf("%d",&data);
A[i]=data;
}
BuildHeap(A,N);
for(i=0;i<N;i++)
{
printf("%d ",A[i]);
}
return 0;
}
The 2 fors that you use must start from 0 to N
When you write:
A[0] <=> address pointed by A + 0 * sizeof(data type of A)
So 0 is the first address of the array
and the last address is N-1
A[N-1] <=> address pointed by A + (N-1) * sizeof(data type of A)

segmentation fault in this code

#include <math.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
void sort(int a[], int n)
{
int i, j;
for (i = 0; i < n - 1; i++)
for (j = i; j < n - 1; j++)
if (a[j] > a[j + 1])
a[j] = a[j + 1] - (a[j + 1] = a[j]);
}
int call(int i, int hit, int t, int h[], int n, int count)
{
static int max = 0;
if (t <= 0)
{
if (count > max)
max = count;
return max;
}
if (h[i] > 0)
{
h[i] -= hit;
if (h[i] <= 0)
count++;
max = call((i + 1) % n, hit, t - 1, h, n, count);//this is line where illegal access to memory is being made
count--;
h[i] += hit;
}
max = call((i + 1) % n, hit, t, h, n, count);
return max;
}
int getMaxMonsters(int n, int hit, int t, int h[]) {
sort(h, n);
int m = call(0, hit, t, h, n, 0);
return m;
}
int main() {
int n;
int hit;
int t;
scanf("%d %d %d", &n, &hit, &t);
int h[100000];
for (int h_i = 0; h_i < n; h_i++) {
scanf("%d", &h[h_i]);
}
int result = getMaxMonsters(n, hit, t, h);
printf("%d\n", result);
return 0;
}
This code computes in the maximum number of monsters that can be killed.
n is no. of monsters
hit is hit value
h[] contains health value of each monster
t is the total time available
So, the maximum number of monsters have to be killed in t seconds and and only one monster per second.
I am getting segmentation fault for illegal access of memory. Unable to understand how am I crossing the array limits.
Ask your debugger or use Valgrind.
it automatically detects memory management bugs. it also profiles your program in detail.
it is too simple to use Valgrind.

Sort elements in array C [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I am trying to create a program that will sort elements in 4 steps (read elements - print elements - sort them - print the sorted version).
I need help with the sorting (third) part.
Here is my code:
/*
* A simple program to sort numbers in correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10
#define SENTINEL -99
int main()
{
int tableFill(int a[], int max);
void tableInsert(int a[], int num, int val);
void tableSort(int a, int n);
void tablePrint(int a, int n);
int num;
int table[MAXSIZE];
int max;
num=tableFill(table,MAXSIZE);
return EXIT_SUCCESS;
}
int tableFill(int a[], int max)
{
int r; // input from scanf
int next; // score from user
int cnt = 0;
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))!= EOF && cnt<max)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
a[cnt++]=next;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
}
void tableInsert (int a[], int num, int val)
{
int pos;
for(pos = num; pos>0 && val<a [pos-1]; pos--)
a [pos] = a [pos -1];
a[pos] = val;
}
void tableSort(int a, int n)
{
}
void tablePrint(int a, int n)
{
int i;
for(i = n -1; i>=0; i++)
{
printf("%i\n",a[i]);
}
}
SOLUTION
I used David C. Rankin's solution and fixed my code. This is my final version:
/*
* A simple program to sort numbers in the correct order
*/
#include <stdio.h>
#include <stdlib.h>
#define MAXSIZE 10 //max elements in array
int main () {
int tableFill (int a[], int max);
void tableSort (int a[], int n);
void tablePrint (const a[], int n);
int arr[MAXSIZE]; //creating an array
int n = tableFill (arr, MAXSIZE); //declaring variable to work with array
tablePrint (arr, n); //prints unsorted values
printf ("Here is your sorted array:\n");
tableSort (arr, n); // sorts values in order
tablePrint (arr, n); // prints sorted values
return 0;
}
// read values from stdin into array up to 'max' values
int tableFill(int a[], int max) {
int r; // input from scanf
int next; // score from user
int cnt = 0; // loop variable
printf("Enter the numbers! \n");
while ((r=scanf("%i", &next))!= EOF && cnt<max)
{
if (r == 0) //invalid input data
{
printf("Nonnumeric data entered. Please enter a number. \n");
while (getchar()!= '\n'); // flush invalid data
}
else
a[cnt++]=next;
}
if(r==1) //another value was read but the array is full
printf("Error - too many values. Array size %i.\n", max);
return cnt;
}
// swap values at array indexes 'i' and 'j'.
void tableSwap (int a[], int i, int min_index)
{
int tmp = a[i];
a[i] = a[min_index];
a[min_index] = tmp;
}
//sort array
void tableSort (int a[], int n)
{
void tableSwap (int a[], int i, int min_index);
int i, j; //loop counters
int min, min_index; //adjusting variables for loops
for (i = 0; i <= n - 2; i++) {
min = a[i];
min_index = i;
for (j = i + 1; j <= n - 1; j++) {
if (a[j] < min){
min = a[j];
min_index = j;
}
}
tableSwap (a, i, min_index);
}
}
//print all elements in array.
void tablePrint (const a[], int n)
{
int i; //variable for print
for (i = 0; i < n; i++)
printf ("%d ", a[i]);
printf ("\n");
}
As pointed out in the comments, qsort is the defacto standard sort routine contained in the C standard library. It is incredibly flexible and incredibly fast due to using a combination of sorting methods optimized for the range of data being sorted. Beginning C users generally have difficulty writing the compare functions because it involves the use of pointers. Just take the time needed to write a few compare functions are get comfortable with it -- it will save you a lot of grief in the long run.
That said, before looking at both alternative sorts, C-style generally uses lower-case for variable and function names. Leave camelCase names for C++. See e.g. NASA - C Style Guide, 1994
Sorting with the old-slow bubblesort. For sorting anything with greater than 100 elements, the efficiency of the bubblesort craters. It is hundreds of times slower than qsort for any large number of element. That being said, putting a bubblesort together that incorporates your tableswap requirement is straightforward:
/** sort array using slow old bubblesort */
void tablebubblesort (int *a, int n)
{
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) /* For decreasing order use < */
tableswap (a, n, j, j+1);
}
}
}
Your tableswap function will look similar to:
/** swap values at array indexes 'i' and 'j'. */
void tableswap (int *a, int n, int i, int j)
{
if (i >= n || j >= n) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
Simply call the function in your code with tablebubblesort (arr, n);
qsort is even simpler. The full function (you really don't need a separate function) is:
/** qsort the array */
void tablesort (int *a, int n, size_t sz)
{
qsort (a, n, sz, compare);
}
It requires a compare function which is simply:
/** qsort compare function */
int compare (const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
Don't let you eyes roll over in your head simply because you see const void *a, etc.. it is really straight forward. Your a and b pointers represent a pointer to individual integers in the array (e.g if say a[1] = 5, the pointer is just &a[1] the address of the element). So taking the compare function apart, knowing you are just passing the address of an element (e.g. integer pointers) to compare, you would write it long-hand as follows:
int compare (const void *a, const void *b)
{
int *value1 = (int *)a; /* cast each to int pointer */
int *value2 = (int *)b;
if (*value1 > *value2) /* compare dereferenced values */
return 1;
if (*value1 < *value2)
return -1;
return 0;
}
Or, if it makes you happier, you can cast and dereference all at once and then just operate on integer values:
int compare (const void *a, const void *b)
{
int value1 = *(int *)a;
int value2 = *(int *)b;
if (value1 > value2)
return 1;
if (value1 < value2)
return -1;
return 0;
}
Either way it is the same. (arguably, the first is the most proper because it avoid the "appearance" of type punning pointers and derefencing void values, but that is for another day) There is no magic, just do it enough times for integers, strings, structs, etc.. until it sinks in. It's more than worth the time.
Putting the rest of the pieces together, you could meet your requirements with something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXI 128
int tablefill (int *a, int max);
void tableinsert (int *a, int *n, int max, int num, int val);
void tableswap (int *a, int n, int i, int j);
void tablesort (int *a, int n, size_t sz);
void tablebubblesort (int *a, int n);
void tableprint (int *a, int n);
int compare (const void *a, const void *b);
int main (void) {
int arr[MAXI] = {0};
int n = 0;
printf ("enter array values ([ctrl+d] to end)\n");
n = tablefill (arr, MAXI);
tableprint (arr, n);
printf ("\ninsert '5' as the '2nd' element of array\n");
tableinsert (arr, &n, MAXI, 2, 5);
tableprint (arr, n);
printf ("\nswap indexes '1' and '3'\n");
tableswap (arr, n, 1, 3);
tableprint (arr, n);
printf ("\nsorted array\n");
#ifdef WQSORT
tablesort (arr, n, sizeof *arr); /* gcc -DWQSORT to use tablesort */
#else
tablebubblesort (arr, n);
#endif
tableprint (arr, n);
return 0;
}
/** read values from stdin into array up to 'max' values. */
int tablefill (int *a, int max)
{
int idx = 0, tmp;
while (idx + 1 < max && scanf ("%d", &tmp) == 1)
a[idx++] = tmp;
return idx;
}
/** insert 'val' as the 'num' element in 'a' ('num - 1' index),
* update 'n' to current number of elements.
*/
void tableinsert (int *a, int *n, int max, int num, int val)
{
if (num >= max || *n + 1 == max) return;
if (num >= *n) { a[num] = val; (*n)++; return; }
int i;
for (i = *n; i >= num; i--)
a[i] = a[i-1];
a[i] = val;
(*n)++;
}
/** swap values at array indexes 'i' and 'j'. */
void tableswap (int *a, int n, int i, int j)
{
if (i >= n || j >= n) return;
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
/** qsort the array */
void tablesort (int *a, int n, size_t sz)
{
qsort (a, n, sz, compare);
}
/** sort array using slow old bubblesort */
void tablebubblesort (int *a, int n)
{
int i, j;
for (i = 0; i < n - 1; i++) {
for (j = 0; j < n - i - 1; j++) {
if (a[j] > a[j + 1]) /* For decreasing order use < */
tableswap (a, n, j, j+1);
}
}
}
/** print all elements in array. */
void tableprint (int *a, int n)
{
if (!a) return;
int i;
for (i = 0; i < n; i++)
printf (" a[%2d] : %d\n", i, a[i]);
}
/** qsort compare function */
int compare (const void *a, const void *b)
{
return (*(int *)a - *(int *)b);
}
The code contains both the bubblesort and qsort version of the sort. You simply pass the define -DWQSORT to compile with the qsort code or compile without it for the bubblesort. e.g.
Compile Both Versions
$ gcc -Wall -Wextra -Ofast -o bin/array_fill array_fill.c
$ gcc -Wall -Wextra -Ofast -DWQSORT -o bin/array_fill_qsort array_fill.c
Example Use/Output
$ echo "1 4 2 3" | ./bin/array_fill
enter array values ([ctrl+d] to end)
a[ 0] : 1
a[ 1] : 4
a[ 2] : 2
a[ 3] : 3
insert '5' as the '2nd' element of array
a[ 0] : 1
a[ 1] : 5
a[ 2] : 4
a[ 3] : 2
a[ 4] : 3
swap indexes '1' and '3'
a[ 0] : 1
a[ 1] : 2
a[ 2] : 4
a[ 3] : 5
a[ 4] : 3
sorted array
a[ 0] : 1
a[ 1] : 2
a[ 2] : 3
a[ 3] : 4
a[ 4] : 5
$ echo "1 4 2 3" | ./bin/array_fill_qsort
<same outoput>
Look over all the code and let me know if you have questions. This is basic meat and potatoes C and you need to make sure you understand each line, and each character in each line. Take it slow.
Regarding
int tableFill(int a[], int max);
void tableInsert(int a[], int num, int val);
void tableSort(int a, int n);
void tablePrint(int a, int n);
You're declaring the prototypes inside main which is not usually done. They are usually declared in global scope so that they stay put till the end.
Regarding
int tableFill(int a[], int max)
You're not returning anything. Since you're dealing with the pointers you could change int to void.
Regarding
void tableInsert (int a[], int num, int val)
Ask yourself from where you are calling this function.
Regarding
void tableSort(int a, int n)
{
}
See this guide which explains sorts.
Regarding :
void tablePrint(int a, int n)
{
int i;
for(i = n -1; i>=0; i++)
{
printf("%i\n",a[i]);
}
}
Since you're printing an array,so one parameter to this function should be an array.

Resources