Logic Help: Calculating primes of a range of numbers with multiple threads - c

I've been tasked to calculate prime numbers using multiple threads. The user provides a range of numbers, and how many threads to use to find the prime numbers.
So for example, the range is 2 to 100 inclusive and we want to use 3 threads.
What I want to happen is the following:
Thread 1 found 2 3 5 7 11 13 17 19 23 29 31
Thread 2 found 37 41 43 47 53 59 61 67
Thread 3 found 71 73 79 83 89 97
Each thread is going to need to be supplied a start range and an end range. I have determined that a data structure would be the most appropriate for this, such as:
typedef struct Data{
int start;
int end;
}Data;
I can't figure out how to create these sub-ranges. I know I'll have to divide the max end range by how many threads we want, and getting the first threads range is easy but I'm lost after that. This seems like a simple issue that I am making entirely too complicated.
This is where I'm at:
int start, end, nthreads, div;
start = atoi(argv[1]);
end = atoi (argv[2]);
nthreads = atoi (argv[3]);
div = end/nthreads;
for (int i = 0; i < nthreads; i++){
if (i == 0){
//first iteration, start is start and end is the div
data.start = start;
data.end = div;
}
else{
//this is where I am lost
data.start = ??
data.end = div*i;
}
//create the thread with our data
//calculations is handled in threadCreate()
pthread_create(&tid, NULL, threadCreate, (void*)data);
}

From your code, you want to remove the if (i==0) and simply set this:
data.start = start + div * i
data.end = start + div * (i + 1) - 1;
Be cautious though, you may want to redefine div as (end-start) / nbthreads.
You will then quickly realize that some ranges are harder to find prime numbers.
I would recommend using OpenMP which is made exactly for this kind of usage. This would simplify your threading by automatically splitting your for loop. This would allow you to easily use a dynamic task assignation scheme which will automatically balance thread assignation of easier and harder ranges in order to end the computation faster.

Note that in your else you are putting
data.end=div*i;
but you initialized you i with 0 so when else statement would be executed for the first time then data.end will have the value equals to div. And take
div = (end-start)/nthreads;
Try something like
else{
data.start = (div)*(i))+1;
data.end = data.start+div-1;
}

Depends on how you want to go about it:
a) split into even-sized blocks
b) split into interleaved blocks
e.g. start = 10, end = 90, n = 3 threads
you could either go:
thread1 = 10,11,12,13,...
thread2 = 40,41,42,43,...
thread3 = 70,71,72,73,...
or
thread1 = 10, 13, 16, 19, ...
thread2 = 11, 14, 17, 20, ...
thread3 = 12, 15, 18, 21, ...

Related

C program to check lottery numbers: why some tests fail?

This program takes as an input the following lines:
23 12 33 19 10 8
5
23 19 8 12 60 18
14 60 12 44 54 10
8 3 12 19 33 10
33 15 7 60 12 10
22 12 19 23 33 11
23 12 33 19 10 8 ( The first line ) are the lottery results.
n ( in this specific case, 5 ) informs how many lines will follow below.
Each line has 6 numbers. The number order doesn't matter.
The rules are: numbers range from 1 to 60 ( including 1 and 60 ) and they never repeat themselves in the same line.
The variable "quadra" stores how many lines have got 4 numbers right.
The variable "quina" stores how many lines have got 5 numbers right.
The variable "sena" stores how many lines have got 6 numbers right.
So, a computer program is running some tests over my code below and it's claiming that it goes wrong for most of them, but I can't see what's the problem here. Does anybody have a clue? Is this code wrong, or is there something wrong with the software that's testing this code?
#include <stdio.h>
int main(){
int mega[6];
int v[50500][6];
int n,swap;
int i,j,k; //counters
int quadra,quina,sena;
quadra = 0;
quina = 0;
sena = 0;
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
scanf("%i",&n);
for(i=0;i<n;++i){
for(j=0;j<6;++j){
scanf("%i",&v[i][j]);
}
}
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=0;k<6;++k){
if(v[i][j] == mega[k]){
v[i][j] = 61;
}
}
}
}
//reverse bubble sort
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=j+1;k<6;++k){
if(v[i][j] < v[i][k]){
swap = v[i][k];
v[i][k] = v[i][j];
v[i][j] = swap;
}
}
}
}
for(i=0;i<n;++i){
for(j=0;v[i][j] == 61 && j<6;++j);
if(j == 4) ++quadra;
else if(j == 5) ++quina;
else if(j == 6) ++sena;
}
return 0;
}
Your code is true, I understood and tried the flow of it. Looks fine but if you dont need to sort everyline (and use j as a counter in this loop for(j=0;v[i][j] == 61 && j<6;++j); ), you can use simpler ifstatements to compare real lottery results with the ones that entered. What I mean is that your algorithm is a little complex. Try a simple one and see how it works.
Yes, there are a couple of noteworthy issues with your code:
Compile time indicates possibility of uninitialized variable:
But, run-time results in fatal run-time at unknown source location. Stack overflow. It is likely due to this line:
int v[50500][6];
Increase your stack size. It needs to be about 2.5Mbytes for v alone.
Also, this line may not be what you intended:
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
^
If you meant to loop around the remainder of the code, remove the ; after the for() statement, and use curly braces:
for(i=0;i<6;++i) scanf("%i",&mega[i]) //first line, lottery results
{
scanf("%i",&n);
....

I am trying to set a value to an array, but I can't seem to figure out why what I did on line 31 is wrong

I have a data file in the format <0:00> - <19321> , <1:00> - <19324>, up to <24:00> - <19648>, so for every hour there is the total power used so far(the total is incremented), I am supposed to calculate the power used, find the average, and the highest usage of power and its index(time), (I don't need help with finding the max power used at its time index). I traced the problem down to line 31, but I don't understand why what I did was wrong. Can someone explain to me why the code in line 31 isn't saving the value of power used into the array? And how I can fix it? Thanks in advance!
float compute_usage(int num, int vals[], int use[], int *hi_idx)
15 {
16 int i;// i is a general counter for all for loops
17 int r1, r2, u, v, pow_dif, temp;//for loop 1
18 int tot;//for loop 2
19 int max_use, init, fina, diff;//for loop 3 //don't have to worry about this for loop, I am good here
20 float avg;//average power used
21
22 for(r1=r2=i=u=v=0;i<num;i++)//for loop 1
23 {
24 r1= vals[v++];//I set values of every hour as reading 1 & 2(later)
25 #ifdef DEBUG
26 printf("pre-debug: use is %d\n", use[u]);
27 #endif
28 if(r1!=0 && r2!=0)
29 {
30 pow_dif = (r1 - r2);//I take the to readings, and calculate the difference, that difference is the power used in the interval between a time period
31 use[u++] = pow_dif; //I'm suppose to save the power used in the interval in an array here
32 }
33 r2=r1;//the first reading becomes the second after the if statement, this way I always have 2 readings to calculate the power used int the interval
34 #ifdef DEBUG
35 printf("for1-debug3: pow_dif is %d\n", pow_dif);
36 printf("for1-debug4: (%d,%d) \n", u, use[u]);
37 #endif
38
39 }
40 for(tot=i=u=0;i<num;i++)//for loop 2
41 {tot = tot + use[u++];}
42
43 avg = tot/(num-1);
44 #ifdef DEBUG
45 printf("for2-debug1: the tot is %d\n", tot);
46 printf("for2-debug2: avg power usage is %f\n", avg);
47 #endif
Just to understand, how did you figure out that the code in line 31 is problematic? Is it the printf statement in line 36?
When you do this:
use[u++] = pow_dif; //I'm suppose to save the power used in the interval in an array here
printf("for1-debug4: (%d,%d) \n", u, use[u]);
The "u" variable in printf statement is incremented in the previous operation (u++), so you are looking past the element you changed.
use[u++] = pow_dif; //I.e. u=0 here, but u=1 after this is executed.
printf("...\n", u=1, use[1]);
What is the "i" for in this loop? Why don't you try "u++" in the for statement instead of "i++" and remove the "u++" in the use assignment expression?

What is a fast way to compare a big list of pairs of integers?

Thing is, we have N pairs of integers, as an example:
23 65
45 66
22 65
80 20
30 11
11 20
We say one pair is bigger than another one if both numbers from one pair are greater than the other two, or if the first number is equal and the other one is bigger, or vice-versa. Otherwise, if you can't compare them that way, then you can't establish which one is bigger.
The idea is to know, for each pair, how many pairs it is bigger to (in the example, the first pair is bigger than the third and the last one, therefore the answer for the first is 2).
The trivial solution would be O(n2), which is simply comparing every pair to every other one and adding one to a counter for each positive match.
Can anybody come up with a faster idea?
I have implemented the simple solution (N2), works reading from "sumos.in":
#include <iostream>
#include <fstream>
#define forn(i, x, N) for(i=x; i<N; i++)
using namespace std;
ifstream fin("sumos.in");
ofstream fout("sumos.out");
struct sumo{
int peso, altura;
};
bool operator < (sumo A, sumo B) {
if( A.altura == B.altura )
if( A.peso < B.peso )
return true;
else
return false;
else
if( A.peso == B.peso )
if( A.altura < B.altura )
return true;
else
return false;
else
if( (A.altura < B.altura) && (A.peso < B.peso) )
return true;
else
return false;
}
int L;
sumo T[100000];
int C[100000];
int main()
{
int i, j;
fin >> L;
forn(i, 0, L)
fin >> T[i].peso >> T[i].altura;
forn(i, 0, L)
forn(j, 0, L)
if( j!=i )
if( T[j]<T[i] )
C[i]++;
forn(i, 0, L)
fout << C[i] << endl;
return 0;
}
Example of input:
10
300 1500
320 1500
299 1580
330 1690
330 1540
339 1500
298 1700
344 1570
276 1678
289 1499
Outputs:
1
2
1
6
3
3
2
5
0
0
I solved this problem by using a segment tree. If you wish to see the implementation: http://pastebin.com/Q3AEF1WY
I think I came up with a solution to this but it is rather complex. The basic idea is that there are these groups where the pairs can be arranged in dominated order for example:
11 20 30 11
22 65 80 20
23 65
45 65
If you start thinking about taking your pairs and trying to create these groupings you realize you will end up with a tree structure. For example imagine we added the pair 81 19 to the list and add a pair (-∞, -∞)
(-∞, -∞)
/ \
11 20 30 11 ---\
22 65 80 20 81 19
23 65
45 65
If you follow the path from a node to the root you will count how many pairs the current pair dominates. From this example it kind of looks like you can use binary search to figure out where to insert a pair into the structure. This is where the complexity troubles start. You can't do a binary search/insertion on a linked list. However there is a very neat data structure called a skip list you might use. You can basically search and insert in O(logn) time.
There's still one problem. What if there are tons of these groupings? Imagine a list like
11 20
12 19
13 18
14 17
You're tree structure will look like:
(-∞, -∞)
/ / \ \
11 20 12 19 13 18 14 17
Again use skip lists to order these nodes. I think this will require two different kinds of nodes in the tree, a horizontal type like above and a vertical type like in the first examples. When you are done constructing the tree, do a iterate the tree with DFS while recording the current depth to associate each pair with the number of nodes it dominates.
If the above algorithm is correct you could insert a the pair into the tree in O(logn) time and thus all the pairs in O(nlogn) time. The DFS part will take O(n) time thus constructing the tree and associating a pair with the number it dominates will take O(nlogn) time. You can sort the pairs based on the number of dominations in O(nlogn) time so the whole process will take O(nlogn) time.
Again there is probably a simpler way to do this. Good luck!
You can use. A sort. like this
int z = {23,65,45, 66,22,65,80,20,30,11,11, 20};
int i, j, k, tmp;
for (i=1; i<n; i++){
j= n-i-1;
for (k=0; k<=j; k++)
//Put attention on this block.
if (z[k]>z[k+1]){
tmp= z[k];
z[k]= z[k+1];
z[k+1]= tmp;
}
}

Arrays and for loops trouble

I am doing an array exercise and I almost finished it.I have trouble finishing the last part.I create two arrays that store coursework points and exam points and then using a third array I calculate the module result(it is determined by both exam and coursework points). I got this part working and assuming I have 5 modules the output is 5 numbers.However I want to calculate my stage mark so if I have 5 modules I get their marks,add them together and then divide them by 5.Here is my problem I am using for loop because that is the only way it will work(as far as I know) so given that I already have my module result I use this for loop to calculate the stage result:
for(int i = 0; i < module_result.length; i++)
{
sum = sum + module_result[i];
System.out.println(sum/5);
}
I saw in this site similar question and I used the code in the answers.I can use enhanced for loop as well.
So given that coursework array={45,70,60,55,80} and exam array={83,72,45,25,89} my module results are 64,71,60,87. By using the above for loop I get anticipated outcome:
10
22
32
37
52
So I get my result. It is 52. But I don't want the rest of the numbers.
My question is how can I get just that number(52). I guess it is not possible by using for loop because it will inevitably is going to loop 5 times not one. I thought about using while loop but I don't see how I will get much different outcome.
I'm not sure if I totally understand the question, but I think this is what you're going for:
for(int i = 0; i < module_result.length; i++)
{
sum = sum + module_result[i];
}
System.out.println(sum/5);
All you have to do is simply move the println statement outside of the loop (if I understand the question correctly).
If you just want to print out the last number, just do a condition in the for loop that would print out at the index just before the length like this:
for (int i = 0; i < module_result.length; i++) {
if (i == module_result.length - 1) {
// print results
}
else {
// Do calculations
}
}
OK here is my code.
public int[] computeResult(int []courseWork,int[] examMarks ){
int[] module_result = new int[6];
for(int i=0;i<module_result.length;i++){//CALCULATE EACH MODULE
module_result[i]= ((courseWork[i] * cw[i]) + (examMarks[i] * (100 - cw[i]))) / 100;//THIS LINE IS SIMPLY A CONDITION HOW TO CALCULATE A MODULE YOU DON'T NEED TO KNOW WHAT IS HAPPENING INSIDE
}
int sum = 0;
for(int i = 0; i < module_result.length; i++)//USE THIS FOR LOOP TO ADD THE MODULES TOGETHER.
{
sum = sum + module_result[i];
// Add this extra line
// This allows you to only print out the value when you reach the end
if (i == module_result.length - 1) {
System.out.println(sum/6);
}
}
return module_result;
}
However here is what happens-the first for loop calculate the module results.Say they are as follows in the output console:
64
71
60
31
87
33
Next the second for loop is adding them together-first is 64,next loop at 71 to 64 and you get 135,next add to 135 the next module result 60 and so on until I get the total sum of all 6 modules which is just in this example 346 and then divide it by 6 to get my stage result.So I need in my output console just 346/6.Nothing else no zeros no nothing.
What my current code does is this-the second loop star running,it already knows my module results(they have been calculated) and so it starts- the first one is 64,divide it by 6 I get outcome 10,then the loop add 71 to 64 get 135 and divide it by 6 and so on until it reaches the number 346 and divide it by 6.So I get this output:
10
22
32
37
52
57
I don't need 10,22,32,37 and 52 they hold no meaning.I just need 57.What your solution will give me is this outcome:
0
0
0
0
0
57
It still gives unnecessary numbers.

Traversing INT array in two ways

Traversing INT array in two ways is a robotic funny code (in C).
I have an array of positions like this: int pos[] = {0, 45, 90, 135, 180, 135, 90, 45};
These positions are used to move a servo motor.
45 90 135
\ | /
\ | /
\ | /
0 ----------- 180
In main loop() I check distance from an obstacle, and if it's < xx Cm my servo must rotate to next step (next array position) until it finds a free way ( > xx Cm ).
My main is easy:
int main (int argc, const char * argv[]) { for (;;) find(); }
and my core function (find) is this:
void find() {
for ( i=0; i<sizeof(pos); i++ ) // Traversing position array
{
distance = rand() % 7; // Simulate obstacle distance
move( pos[i] ); // Simulate movements
if (i==sizeof(pos)) { i=1; } // Try to reset the "i" counter. PROBLEM!
if ( distance<=5 ) continue; // Is there an obstacle?
sleep(2); // Debug sleep
find(); // Similar recursion
}
}
I don't know what is wrong in this code, but I need to move servo until is there not an obstacle.
Example:
At position 90 I find an obstacle. I want to loop array from left to right and viceversa controlling distance every step. If I don't find a freeway, print("ko") else print("ok").
How do I fix this code to work correctly?
You really want i < sizeof(pos) / sizeof(*pos) rather than i < sizeof(pos). The size of an array is not the number of its elements but rather the total byte count it occupies in memory.
sizeof(pos) yields 8 * sizeof(int). If an int is 4 bytes, you are looping 32 times instead of 8.
Also, i == sizeof(pos) will never be true in the body of the loop because the condition of the for statement limits i to sizeof(pos) - 1.
If I understand your question correctly, you want the servo to make a sweeping movement from left to right and then back from right to left. Measuring the distance to an object that can be in front of the robot at each angle. If there is a free way ahead of the robot, the find method returns.
int pos[] = {0, 45, 90, 135, 180, -1};
void find()
{
int i = 0;
int direction = 1;
do {
move(pos[i]);
i += direction;
if (pos[i+direction] == -1) direction = -1;
if (i==0) direction = 1;
} while(measure_distance() <= 5);
}
Instead of recursion, there is a while loop that only exits when there is a distance greater then 5.
The 'pos' array has a sentinel at the end (-1). This is an invalid angle and can be used to find the end of the array. There is no need to calculate the number of elements.
The left-right, right-left movement comes from using the 'direction' variable. It is rather easy to detect either the beginning (i==0) or the end of the 'pos' array (pos[i+1] == -1), at which point we reverse the direction.
There is also no need to repeat the angles after 180 degrees. The sequence we get is:
0 45 90 135 180 135 90 45 0 45 90 ...
We can even reduce the code with one line...
...
if (pos[i+direction] == -1 || i == 0) direction *= -1;
...
Cheers,
Johan
Don't forget to initialize your rand function using
/* initialize random seed: */
srand ( time(NULL) );
distance = rand() % 7;
It's probably good practise to say:
#define POSLENGTH 8
and then iterate using i<POSLENGTH: as others have pointed out using sizeof(pos) is probably not going to work.
Also, arrays in C are 0 based: elements go 0,1,2,3,...n-1.
So, you need to say:
if (i==POSLENGTH-1) i=0;
Try using a while loop instead of a for loop. Increment the value when there is no obstacle and break when you find an obstruction:
{
......
......
i = rand()%7;
move( pos[i]);
if (i<5)
break;
else
continue;
.......
.......
}
This will randomly choose the position until you get an obstacle and also there will be no need to reset it as the loop will automatically break on encountering an obstacle.

Resources