I have N jobs with varied work loads that is to be distributed among n persons so that the work load is as balanced as possible.
e.g-we have to divide 5 jobs with work loads <1,2,3,4,5> between 3 persons. The best way would obviously be to distribute as follows:-
<1,4>,<2,3>,<5>.
Thus the problem is to minimize
z=abs(a-b)+abs(b-c)+abs(c-a)
where a, b, c are the workloads of the three persons.What would be the most efficient way to solve the problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int *insort(int *var, int elem)
{ // insert elem into sorted variable array var[1..n] (*var holds n)
int n = var ? *var : 0;
var = realloc(var, (1 + ++n) * sizeof *var);
if (!var) exit(1);
*var = n;
int i;
for (i = 1; i < n; ++i) if (elem < var[i]) break;
memmove(var+i+1, var+i, (n-i) * sizeof *var);
var[i] = elem;
return var;
}
main()
{ // distribute jobs characterized by workloads among n persons
int n, i, j, *jobs = NULL;
printf("number of persons? "); scanf("%d", &n);
printf("job workloads? ");
while (scanf("%d", &i) > 0) jobs = insort(jobs, i);
int *w, *work[n], load[n];
for (i = 0; i < n; ++i) work[i] = NULL, load[i] = 0;
if (n > 0 && jobs) do
{ // assign the most strenuous job to the least busy person
w = insort(work[0], j = jobs[(*jobs)--]);
j += load[0];
for (i = 1; i < n; ++i) if (load[i] > j) break;
memmove(load, load+1, --i * sizeof *load), load[i] = j;
memmove(work, work+1, i * sizeof *work), work[i] = w;
} while (*jobs);
for (i = 0; i < n; ++i, puts(""))
if (w = work[i]) do printf(" %d", w[(*w)--]); while (*w);
}
sample run:
number of persons? 3
job workloads? 1 2 3 4 5.
5
3 2
4 1
Related
How do I make my code more efficient (in time) pertaining to a competitive coding question (source: codechef starters 73 div 4):
(Problem) Chef has an array A of length N. Chef wants to append a non-negative integer X to the array A such that the bitwise OR of the entire array becomes = Y .
Determine the minimum possible value of X. If no possible value of X exists, output -1.
Input Format
The first line contains a single integer T — the number of test cases. Then the test cases follow.
The first line of each test case contains two integers N and Y — the size of the array A and final bitwise OR of the array A.
The second line of each test case contains N space-separated integers A_1, A_2, ..., A_N denoting the array A.
Please don't judge me for my choice of language .
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int* binary_number(int n) // returns pointer to a array of length 20(based on given constrains) representing binary
{
int* ptc;
ptc = (int*) malloc(20*sizeof(int));
for(int i = 0; i < 20; i++)
{
if((n / (int) pow(2,19-i)) > 0){*(ptc + i) = 1;}
else {*(ptc + i) = 0;}
n = n % (int) pow(2,19-i) ;
}
return ptc;
}
int or_value(int* ptc, int n) // Takes in pointers containing 1 or zero and gives the logical OR
{
for(int k = 0; k < n; n++)
{
if(*ptc == *(ptc + 20*k)){continue;} // pointers are 20 units apart
else{return 1;break;}
}
return *ptc;
}
int main(void) {
int t; scanf("%d", &t);
for (int i = 0; i < t; i++)
{
int n, y;
scanf("%d %d", &n, &y);
int a[n];
for(int j = 0; j < n ; j++)
{
scanf("%d", &a[j]);
}
int b[20*n];
for (int j = 0; j < n; j++)
{
for (int k = 0; k < 20; k++)
{
b[20*j + k] = *(binary_number(a[n])+k);
}
}
int c = 0;
int p = 0;
for (int j = 0; j < 20; j++)
{
if ((*(binary_number(y) + j) == 1) && (or_value((&b[0] + j),n) == 0)){c = c + pow(2,19 - j);}
else if ((*(binary_number(y) + j) == 0) && (or_value((&b[0] + j),n) == 1)){p = 1; break;}
}
if (p==1){printf("-1");}
else {printf("%d\n", c);}
}
return 0;
}
I am writing a program to read an integer n (0 < n <= 150) and find the smallest prime p and consecutive prime q such that q - p >= n.
My code works, but it runs for about 10 seconds for larger n.
#include <stdio.h>
#include <stdlib.h>
int isPrimeRecursive(int x, int i){
if (x <= 2){
return (x == 2 ? 1:0);
}
if (x % i == 0){
return 0;
}
if (i * i > x){
return 1;
}
return isPrimeRecursive(x, i+1);
}
int findSuccessivePrime(int x){
while (1){
x++;
if (isPrimeRecursive(x, 2)){
return x;
}
}
return 0;
}
int findGoodGap(int n, int *arr){
int prime = findSuccessivePrime(n*n);
while (1){
int gap;
int succPrime;
succPrime = findSuccessivePrime(prime);
gap = succPrime - prime;
if (gap >= n){
arr[0] = succPrime;
arr[1] = prime;
return gap;
}
prime = succPrime;
}
return 0;
}
int main(int argc, char *argv[]){
int n;
int arr[2];
scanf("%d", &n);
int goodGap;
goodGap = findGoodGap(n, arr);
printf("%d-%d=%d\n", arr[0], arr[1], goodGap);
return 0;
}
How can I make the program more efficient? I can only use stdio.h and stdlib.h.
The algorithm is very inefficient. You're recalculating the same stuff over and over again. You could do like this:
int n;
// Input n somehow
int *p = malloc(n * sizeof *p);
for(int i=0; i<n; i++) p[i] = 1; // Start with assumption that all numbers are primes
p[0]=p[1]=0; // 0 and 1 are not primes
for(int i=2; i<n; i++)
for(int j=i*2; j<n; j+=i) p[j] = 0;
Now, p[i] can be treated as a boolean that tells if i is a prime or not.
The above can be optimized further. For instance, it's quite pointless to remove all numbers divisible by 4 when you have already removed all that are divisible by 2. It's a quite easy mod:
for(int i=2; i<n; i++) {
while(i<n && !p[i]) i++; // Fast forward to next prime
for(int j=i*2; j<n; j+=i) p[j] = 0;
}
As Yom B mentioned in comments, this is a kind of memozation pattern where you store result for later use, so that we don't have to recalculate everything. But it takes it even further with dynamic programming which basically means using memozation as a part of the algorithm itself.
An example of pure memozation, that's heavily used in the C64 demo scene, is precalculating value tables for trigonometric functions. Even simple multiplication tables are used, since the C64 processor is MUCH slower at multiplication than a simple lookup. A drawback is higher memory usage, which is a big concern on old machines.
I think it would be a good approach to have all of the prime numbers found and store it in an array; in that case you wouldn't need to do divisions from scratch to find out whether a number is a prime number or not
This is the algorithm which checks if the number "n" is prime simply by doing divisions
bool isPrime(int n) {
if(n <= 1) return false;
if(n < 4) return true;
if(n % 2 == 0) return false;
if(n < 9) return true;
if(n % 3 == 0) return false;
int counter = 1;
int limit = 0;
while(limit * limit <= n) {
limit = limit * 6;
if(n % (limit + 1) == 0) return false;
if(n % (limit - 1) == 0) return false;
}
return true;
}
If you use the algorithm above which its time complexity is in order of sqrt(n) , your overall time complexity would be more than n^2
I suggest you to use "Sieve of Eratosthenes" algorithm to store prime numbers in an array
Check out this link
https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
Here is the code. I used optimized sieve in Main function.
#include <iostream>
using namespace std;
void Sieve(bool* list, const int n);
void OptimizedSieve(bool* list, const int n);
int main() {
bool list[100 / 2];
for(int i = 0; i < 100 / 2; i++) list[i] = true;
OptimizedSieve(list, 100 / 2);
for(int i = 0; i < 100 / 2; i++){
if(list[i]) cout << (2 * i) + 1 << endl;
}
return 0;
}
void Sieve(bool* list, const int n){
list[0] = false;
list[1] = false;
for(int p = 2; p * p <= n; p++){
if(!list[p]) continue;
for(int j = p * p; j < n; j += p){
if(list[j] == true) list[j] = false;
}
}
}
void OptimizedSieve(bool* list, const int n){
list[0] = false;
for(int p = 3; p * p <= n; p += 2){
if(!list[(2 * p) + 1]) continue;
for(int j = p * p; j <= n; j += 2 * p){
int index = (j - 1) / 2;
if(list[index]) list[index] = false;
}
}
}
Sample Input
2
2
5
Sample Output
0 1 1
0 1 1 2 1 2
I already knew how to transfer an integer to its binary and count how many 1 in its binary.
But my code only can input one integer each time. I want it to input many numbers, like the sample input and sample output. To make question more easy to understand, so I drew a picture. Thank you!!
Thanks all of you!! But I need some time to understand those code and my English is pretty basic, so I couldn't reply you guys soon. But I will understand and reply you as soon as possible!!thank you :D
#include <stdio.h>
int main()
{
int n,cnt=0,m;
scanf("%d",&n);
while(n>0){
m=n%2;
if(m==1){
cnt++;
}
n/=2;
}
printf("%d",cnt);
return 0;
}
In practice, the process can be simplified and accelerated by noticing that if we know the result for i < 2^p, then, for all values in [2^p, 2^(p+1)-1], we have
count(j) = 1 + count(j-2^p)
This method is useful here as we have to provide the result for all values less or equal to n.
Moreover, in order to avoid performing the same calculation at different times, we first calculate the maximum n value, and perform the calculation for this maximum value.
#include <stdio.h>
int main() {
int t;
int check = scanf("%d", &t);
if (check != 1) return 1;
int nn[t];
for (int i = 0; i < t; ++i) {
int check = scanf("%d", &nn[i]);
if (check != 1) return 1;
}
int nmax = 0;
for (int i = 0; i < t; ++i) {
if (nn[i] > nmax) nmax = nn[i];
}
int count[nmax+1];
count[0] = 0;
count[1] = 1;
int pow2 = 1;
do {
pow2 *= 2;
for (int j = pow2; (j < 2*pow2) && (j <= nmax); j++) {
count[j] = 1 + count[j-pow2];
}
} while (pow2 <= nmax+1);
for (int i = 0; i < t; ++i) {
for (int j = 0; j <= nn[i]; ++j) {
printf ("%d ", count[j]);
}
printf ("\n");
}
return 0;
}
Let the number of measured values be t. Now if you want to take t number of integers as input, you have to run a loop t times and perform necessary tasks (like taking value of n, calculating cnt etc) inside that loop. Check the following code snippet:
int main()
{
int n,cnt=0,m;
int numberOfMeasuredValues;
scanf("%d", &numberOfMeasuredValues);
while(numberOfMeasuredValues > 0){
cnt = 0;
scanf("%d",&n);
// perform necessary calculations
printf("%d\n",cnt);
numberOfMeasuredValues--;
}
return 0;
}
In the code numberOfMeasuredValues is the t I've used in the explanation.
You can pre-allocate number of cases and work on them with outer and inner loops. I've added the code with comments below.
#include <stdio.h>
int main(void)
{
int cases; // Number of cases
scanf("%d", &cases);
int* nums = malloc(cases * sizeof *nums); // Allocate enough space.
/* Take the inputs. */
for (int i = 0; i < cases; i++)
{
scanf("%d", (nums + i));
}
int cnt = 0; // Counter for number of 1s.
// Outer loop for going through cases.
for (int i = 0; i < cases; i++)
{
// Inner loop for couting towards inputted number.
for (int j = 0; j < *(nums + i) + 1; j++)
{
/*
* You can Implement this part by yourself if you wish.
*/
for (int k = 0; k < 32; k++)
{
if ((j >> (31 - k)) & 0x01) cnt++; // Increment counter if digit is 1.
}
printf("%d ", cnt);
cnt = 0;
}
printf("\n");
}
return 0;
}
Here's the following code to your problem
#include<iostream>
using namespace std;
int main()
{
int tcs;
cin >> tcs;
while (tcs--) {
int n;
cin >> n;
for (int i = 0 ; i <= n ; i++) {
cout << __builtin_popcount(i) << " ";
}
cout << "\n";
}
return 0;
}
So from the numbers from 1 to n, I have to compute how much the '1' digit occurs. For example: if n is 11, the total numbers is 4 (1, 10, 11). My assignment is saying that i have to use threads for this. This is what I've wrote so far:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct {
int from;
int to;
} th_struct;
void *thread_function(void *param){
th_struct *st = (th_struct *) param;
int count = 0;
int nr;
for(int i = st->from; i <= st->to; i++){
nr = i + 1;
while(nr != 0 ){
if (nr % 10 == 1)
count++;
nr /= 10;
}
}
return (void *) (long) count;
}
int main(int argc, char **argv)
{
int threads, n, count = 0, result;
sscanf(argv[1], "%d", &n);
sscanf(argv[2], "%d", &threads);
th_struct info[threads];
pthread_t tid[threads];
for(int i = 0; i < threads; i++){
if(i == 0)
info[0].from = 0;
else
info[i].from = info[i - 1].to + 1;
info[i].to = info[i].from + n / threads - 1;
if(i < n / threads)
info[i].to++;
pthread_create(&tid[i], NULL, thread_function, &info[i]);
}
for(int i = 0; i < threads; i++){
pthread_join(tid[i], (void**)&result);
count += (int) (long) result;
}
printf("%d\n", count);
}
First command line argument is n, and the second is the number of threads. For n equal to 11, the output should be 4. But if I plug in 11 1 (n=11, nr of threads=1) the output is 5 (instead of 4). If i plug in 11 2 (two threads), the output is 9. The output should be the same, no matter how many threads I have.
I have tested the following code, and it works. It computes the number of '1' correctly (the following is the same as in the funcion "thread_function_ above", just adapted for testing):
int function(int n){
int count = 0;
int nr;
for(int i = 0; i <= n; i++){
nr = i + 1;
while(nr != 0 ){
if (nr % 10 == 1)
count++;
nr /= 10;
}
}
return count;
}
So the problem is thread related (I guess). Since this is my first program with threads, I don't know what the problem is. Thanks!
You have a few problems:
Incorrect input ranges:
info[0].from = 0;
...
if(i < n / threads)
info[i].to++;
Should be:
info[i].from = 1;
...
if (n % 2 == 1 && i + 1 == threads)
info[i].to++;
Invalid range processing:
nr = i + 1;
Should be:
nr = i;
Invalid result receiving.i changes its value while iterating for joining threads and for loop executes more times than intended:
pthread_join(tid[i], (void**)&result);
Should be:
void* result;
pthread_join(tid[i], &result);
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.