How to find reverse relations between jobs? - c++

I've been trying to find reverse relations between jobs. To be more specific I will tell it with an example.
Suppose I have n jobs i.e {0,1,2,3,4,...n}. I also have relations between jobs. I know only successor jobs, i.e., 2 is followed by 4,5. 5 is followed by 7,8 etc. I have it in a text file. I want to obtaing precedence relations between jobs (what is the predecessor job of 5?).
Having text output would be great. I have some code but it does not work.
#include <iostream>
#include <fstream>
#include <iomanip>
#include <cstdlib>
#include <ctime>
using namespace std;
#define TOTAL_ACTIVITY 123
void readFile();
void change ();
void writeFile ();
struct Activity {
int precedessor [3];
int successor [3];
int id;
};
Activity activityList[TOTAL_ACTIVITY];
void main() {
readFile();
change();
writeFile();
}
void readFile() {
ifstream myReadFile;
myReadFile.open("pre.txt");
if (!myReadFile) { //check whether the file can be opened
cerr << "Unable to open file"; // terminate with error
}
while (!myReadFile.eof()) {
int Id,suc1, suc2, suc3;
int t = 0;
while (myReadFile >> Id >> suc1 >> suc2 >> suc3) //data should be in this order
{
activityList[t].id = Id;
activityList[t].successor [0] = suc1;
activityList[t].successor [1] = suc2;
activityList[t].successor [2] = suc3;
t++;
}
}
return;
}
void change() {
int act;
for (int i=1;i<TOTAL_ACTIVITY;i++){
for (int j=0;j<TOTAL_ACTIVITY;j++){
for (int k=0;k<3;k++) {
if (activityList[j].successor[k]==i;)
}
}
}
}
void writeFile() {
ofstream out("out.txt");
out << "id\t" << "Pre1\t" << "Pre2\t" << "Pre3\t"<<"\n";
for (int j = 0; j < TOTAL_ACTIVITY; j++) {
out << activityList[j].id << "\t";
out << activityList[j].precedessor[0]<< "\t";
out << activityList[j].precedessor[1] << "\t";
out << activityList[j].precedessor[2] << "\t";
out << "\n";
}
out.close();
}
Here is a sample input:
ID Successor1 Successor2 Successor3
1 2 3 4
2 6 11 15
3 7 8 13
4 5 9 10
5 20
6 30
7 27
8 12 19 27
9 14
10 16 25
11 20 26
12 14
13 17 18
14 17
15 25
16 21 22
17 22
18 20 22
19 24 29
20 23 25
21 28
22 23
23 24
24 30
25 30
26 31
27 28
28 31
29 32
30 32
31 32
Output should be something like this:
Id Predecesor1 Predecesor2 Predecesor3
........................................
...........................................
...........................................

You are given the successors of a job, but you do not need to retain this information.
For example, if I say: 5 -> 6, 7 meaning that 5 is followed by 6 and 7, then it is equivalent to saying that 6 and 7 are preceded by 5, right.
You can then either:
directly output the precedence when reading the successors
store in an associative container, using the job id as the key and the predecessor as value
Specifics details... are for you to work out to conclude your homework.

Related

How to find the count number of entries in map iterator in C++

I am new in C++.I am using STL Containers.I am mapping the AnimalWeightCAT to unique values of distance travel in km.Using this code
#include <iostream>
#include <map>
#include <sstream>
int main() {
std::istringstream file(
"3 138 3 239 3 440 3 241 3 462 3 432 3 404 2 435 2 514 2 565 3 328 3 "
"138 5 401 5 142 5 404 5 460 5 472 2 418 5 510 2");
// some typedefs to make it simpler:
typedef int AnimalWeightCAT_t;
typedef int distance_t;
typedef int count_t;
typedef std::map<distance_t, count_t> distcount_t;
typedef std::map<AnimalWeightCAT_t, distcount_t> AWeightDistance;
AWeightDistance AWeightDistanceCount; // map AnimalWeightCAT -> distances with counts
AnimalWeightCAT_t AnimalWeightCAT; // temporary variable to read a AnimalWeightCAT
distance_t dist; // temporary variable to read a distance
// read AnimalWeightCAT and distance until the file is depleated and use AnimalWeightCAT and dist as
// keys in the outer and inner map and increase the count:
while (file >> AnimalWeightCAT >> dist) ++AWeightDistanceCount[AnimalWeightCAT][dist];
for(AWeightDistance::iterator adit= AWeightDistanceCount.begin(); adit!= AWeightDistanceCount.end(); ++adit) {
std::cout << "AnimalWeightCAT: " << adit->first << '\n';
for(distcount_t::iterator dcit = adit->second.begin();dcit != adit->second.end();++dcit){
std::cout << '\t' << dcit->first << ' ' << dcit->second << '\n';
}
}
}
How i can find the count of number of distict in indices of AnimalWeightCAT of iterator aditby using map in C++?
Above code display the following output
Output:
AnimalWeightCAT: 2
418 1
435 1
514 1
565 1
AnimalWeightCAT: 3
138 2
239 1
241 1
328 1
404 1
432 1
440 1
462 1
AnimalWeightCAT: 5
142 1
401 1
404 1
460 1
472 1
510 1
I want this kind of output.How?
AnimalWeightCAT: 2 count = 4
AnimalWeightCAT: 3 count = 8
AnimalWeightCAT: 5 count = 6
For count of the second map adit->second.size() will be sufficient so your last loop, in order to look like you desire must be:
for(AWeightDistance::iterator adit = AWeightDistanceCount.begin();
adit != AWeightDistanceCount.end(); ++adit)
{
std::cout << "AnimalWeightCAT: " << adit->first
<< " count: " << adit->second.size() << '\n';
}
or simpler, using a range based for-loop:
for(auto&&[awc, dist_count] : AWeightDistanceCount) {
std::cout << "AnimalWeightCAT: " << awc
<< " count: "<< dist_count.size() << '\n';
}

Calculating difference between two date-times in C++

Problem Summary
I have two strings in the form YYYY-MM-DD:hh:mm:ss and I would like to calculate the time difference between them. For example, the difference between 2021-10-01:03:44:34 and 2021-10-01:03:44:54, should be 20 seconds. However, the result I get is 0.
Code
I have tried the following:
#include <iomanip>
#include <iostream>
using namespace std;
using timestamp = time_t;
auto StringToTimestamp(const string& timeString) -> timestamp {
tm tm {};
stringstream ssBuffer(timeString);
ssBuffer >> get_time(&tm, "%Y-%b-%d:%H:%M:%S");
cout << tm.tm_year << " " << tm.tm_mon << " " << tm.tm_mday << " "
<< tm.tm_hour << " "<< tm.tm_min << " " << tm.tm_sec << " " << endl;
return mktime(&tm);
}
int main() {
string beg = {"2021-10-01:03:44:34"s};
string end = {"2021-10-01:03:44:54"s};
timestamp begTm = StringToTimestamp(beg);
timestamp endTm = StringToTimestamp(end);
double diff = difftime(endTm, begTm);
cout << "Time difference is " << diff << endl;
return 0;
}
Output
121 0 0 0 0 0
121 0 0 0 0 0
Time difference is 0
Expected Output
2021 10 01 03 44 34
2021 10 01 03 04 54
Time difference is 20
Why is the output as such? How can I fix this?
EDIT
I changed this line "%Y-%b-%d:%H:%M:%S" to "%Y-%m-%d:%H:%M:%S" and now the output is
121 9 1 3 44 34
121 9 1 3 44 54
Time difference is 20
Why are the year and month "incorrect"?
You use the conversion specifier%b to get the month but it should be %m:
ssBuffer >> get_time(&tm, "%Y-%m-%d:%H:%M:%S");
%b - parses the month name, either full or abbreviated, e.g. Oct (non-numeric)
%m - parses the month as a decimal number (range [01,12]), leading zeroes permitted but not required
The year and month are correct. 121 is the number of years since 1900 and 9 is the month, zero-based [0,11], which is what's specified for std::tm.

Getting weird values of a variable while using recursion

I wrote a program to print the sum of first 25 natural numbers using a recursive function.
It went fine and I also got the correct output(ie 325).
After that I played a little with my code just to see what happens.
Here is the code :
int su(int sum,int i)
{
if(i<26)
{
sum=sum+i+su(sum,i+1);
cout << sum << endl; // I added this line to see what happens.
// This line wasn't needed but I still
// added it.
}
else
return sum;
}
When I ran this code, it printed weird values of the variable sum.
Here is a screenshot the output : output
The sum of first 25 natural numbers is 325 but that doesn't even show up anywhere in the output. Instead, I got different numbers as in my output.
However when I remove the line cout << sum << endl; from the if statement, I get the expected sum (ie 325).
What is the cause of that?
Your non-void function does not return anything when i is less than 26 and this is undefined behavior. If you checked/turned on the compiler warnings you would see the warning:
warning: control reaches end of non-void function [-Wreturn-type]
}
^
Removing the already pointless else fixes that issue:
#include <iostream>
using namespace std;
int su(int sum,int i)
{
if(i<26)
{
sum=sum+i+su(sum,i+1);
cout<<sum<<endl;
}
// Removed the else. Always returns something
return sum;
}
int main() {
std::cout << su(0, 0) <<std::endl;
}
Output:
25
49
72
94
115
135
154
172
189
205
220
234
247
259
270
280
289
297
304
310
315
319
322
324
325
325
325
Always firstly make sure your recursive function eventually gets out of the loop and returns a value in case it's not void. A much simpler and cleaner way would be like this (a bit like the classic factorial function):
#include <iostream>
int sum (int i) {
if(i == 1) {
return 1;
}
return i + sum(i-1);
}
int main() {
std::cout << sum(25) <<std::endl;
}
Output:
325
If you add std::cout to see what's going on under the hood:
#include <iostream>
int sum (int i) {
std::cout << i << std::endl; // current integer
if(i == 1) {
return 1;
}
return i + sum(i-1);
}
int main() {
std::cout << sum(25) <<std::endl;
}
The output is as expected:
25
24
23
22
21
20
19
18
17
16
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
325
Your function doesn't return anything if not at the end of the recursion. Remove the else keyword it should work.

What data structure is better to use for storing and sorting <int, int> structure?

I have such structure with ids and their count:
product[38] = 10;
product[22] = 7;
product[39] = 18;
I need to use some structure for it. But not sure what should serve better (map, unordered_map, set, vector).
I was trying to use:
map<int, int> product;
But not sure is it the best choice. The only thing that I should do with it - sorting.
As a result I need:
product[39] = 18;
product[38] = 10;
product[22] = 7;
UPD: Sort by value.
A std::map is fine in this case, considering that you are mapping IDs to a count.
For future reference:
You may want to make a struct or std::pair and sore them in std::vector
std::vector<std::pair<int, int>> product;
product.push_back(std::pair<int,int>(38, 27));
product.push_back(std::pair<int,int>(22, 7));
product.push_back(std::pair<int,int>(39, 18));
sort by value:
std::sort(product.begin(), product.end(),
[](const std::pair<int,int>& p1, const std::pair<int,int>& p2){ return p1.second < p2.second; });
I usually do in following way:
create a class/struct of two int member
struct int_pair{
int key;
int value;
}
then create a
vector<int_pair> myvector;
then create two bool compare functions:
bool sort_by_key(int_pair left, int_pair right){
return left.key<right.key;
}
bool sort_by_value(int_pair left, int_pair right){
return left.value<right.value;
}
then sort using std::sort and those bool functions.
std::sort (myvector.begin(), myvector.end(), sort_by_key);
p.s: sorry about the formatting. typing from mobile.
If i had to do this in the confines of your proposed usage (maintain a key-map for quick counter updates, then dump a sorted result), I would likely use an unordered map and a pointer vector. With this I'm assuming the primary reason you want some indexed-key soluton in the first place is to make data processing significantly quicker when updating counts.
In other words, you're looking to get a good speed-bump out of code that does this:
++product[ id ]; // increment counter for product 'id' in our keyed-container.
But still be able to report output sorted not on id, but rather on the accumulated count of each id. That being said, the following, though a little dense, will do exactly that:
#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_map>
#include <iterator>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
typedef std::unordered_map<int, int> Products;
Products product;
// fill with random data for our test.
std::srand((unsigned)time(0));
for (int i=1;i<20;++i)
{
product[i] = rand() % 50 + 1;
cout << setw(3) << i << " ==> " << product[i] << endl;
}
cout << endl;
// now setup a one-shot sort. we're using a vector of
// pointers to our map value type
std::vector<const Products::value_type*> data;
data.reserve(product.size());
std::transform(product.begin(), product.end(), std::back_inserter(data),
[](const Products::value_type& obj) { return std::addressof(obj); });
// sort the vector by value (second)
std::stable_sort(data.begin(), data.end(),
[](const Products::value_type* left, const Products::value_type* right)
{ return left->second < right->second; });
// results are in the vector as pointers. the original map is unchanged.
for (auto ptr : data)
cout << setw(3) << ptr->first << " ==> " << ptr->second << endl;
return EXIT_SUCCESS;
};
Sample Run
1 ==> 42
2 ==> 18
3 ==> 35
4 ==> 1
5 ==> 20
6 ==> 25
7 ==> 29
8 ==> 9
9 ==> 13
10 ==> 15
11 ==> 6
12 ==> 46
13 ==> 32
14 ==> 28
15 ==> 12
16 ==> 42
17 ==> 46
18 ==> 43
19 ==> 28
20 ==> 37
4 ==> 1
11 ==> 6
8 ==> 9
15 ==> 12
9 ==> 13
10 ==> 15
2 ==> 18
5 ==> 20
6 ==> 25
14 ==> 28
19 ==> 28
7 ==> 29
13 ==> 32
3 ==> 35
20 ==> 37
1 ==> 42
16 ==> 42
18 ==> 43
12 ==> 46
17 ==> 46
I've used this method in the past because it is swimmingly-efficient for more complex structures that are expensive to copy into temporary containers for sorting. That the ending pointer-vector references the real data in the map is a nicety that, while probably overkill for this specific problem, certainly has reaps of benefits as a general solution.
That being said, if all you want is an int-to-int dump, sorted on second-int rather than your map key, this will likewise do the trick, though it does replicate data out of your container to accomplish the end-goal:
#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <ctime>
#include <unordered_map>
#include <iterator>
#include <iomanip>
using namespace std;
int main(int argc, char *argv[])
{
typedef std::unordered_map<int, int> Products;
Products product;
// fill with random data for our test.
std::srand((unsigned)time(0));
for (int i=1;i<20;++i)
{
product[i] = rand() % 50 + 1;
cout << setw(3) << i << " ==> " << product[i] << endl;
}
cout << endl;
// copy the values from the map to a sort bed.
std::vector<std::pair<int,int>> vals;
std::copy(product.begin(), product.end(), back_inserter(vals));
std::stable_sort(vals.begin(), vals.end(),
[](const std::pair<int,int>& left, const std::pair<int,int>& right)
{ return left.second < right.second; });
// dump to stdout
for (auto val : vals)
cout << setw(3) << val.first << " ==> " << val.second << endl;
return EXIT_SUCCESS;
}
Sample Output
1 ==> 48
2 ==> 30
3 ==> 25
4 ==> 32
5 ==> 34
6 ==> 21
7 ==> 26
8 ==> 6
9 ==> 50
10 ==> 28
11 ==> 50
12 ==> 32
13 ==> 35
14 ==> 17
15 ==> 33
16 ==> 30
17 ==> 13
18 ==> 1
19 ==> 50
18 ==> 1
8 ==> 6
17 ==> 13
14 ==> 17
6 ==> 21
3 ==> 25
7 ==> 26
10 ==> 28
2 ==> 30
16 ==> 30
4 ==> 32
12 ==> 32
15 ==> 33
5 ==> 34
13 ==> 35
1 ==> 48
9 ==> 50
11 ==> 50
19 ==> 50
You could simply use boost.bimap. Its is a little work to understand it but its worth and I think its fits exactly your use case.

segmentation fault on getline in Ubuntu

I'm having the famous segmentation fault. I've tracked it down to a single line in the code (getline). Here's someone with a similar issue, also on Ubuntu:
http://www.daniweb.com/software-development/cpp/threads/329191
Note that getline returns -1 after the segmentation fault, but it couldn't have been really the end of the stream (in my case).
When the stream is smaller, everything goes ok. As we can deduce from the output, the segmentation fault is on line 98.
1 /*
2 * File: RequestDispatcher.cpp
3 * Author: albert
4 *
5 * Created on July 8, 2011, 7:15 PM
6 */
7
8 #include "iostream"
9 #include "fstream"
10 #include "stdlib.h"
11 #include "stdio.h"
12 #include "cstring"
13 #include "algorithm"
14
15 #include "RequestDispatcher.h"
16 #include "Functions.h"
17
18 #define PROXIES 1
19
20 RequestDispatcher::RequestDispatcher()
21 {
22 }
23
24 RequestDispatcher::RequestDispatcher(const RequestDispatcher& orig)
25 {
26 }
27
28 RequestDispatcher::~RequestDispatcher()
29 {
30 }
31
32 int RequestDispatcher::addRequest(string host, string request, IResponseReceiver* response_receiver)
33 {
34 RequestInfo info;
35 info.request_index = request_info.size();
36 info.host = host;
37 info.request = request;
38 info.response_receiver = response_receiver;
39 request_info.push_back(info);
40 return info.request_index;
41 }
42
43 void RequestDispatcher::run()
44 {
45 if (request_info.size()==0)
46 {
47 return;
48 }
49 FILE* pipe[PROXIES];
50 int per_proxy = (request_info.size() + PROXIES - 1) / PROXIES;
51 int count_pipes = (request_info.size() + per_proxy - 1) / per_proxy;
52 for (int pipe_index=0; pipe_index<count_pipes; ++pipe_index)
53 {
54 int from = pipe_index * per_proxy;
55 int to = min(from + per_proxy, int(request_info.size()));
56 cout << "FROM: "<< from << "; TO: " << to;
57 const char* cmd = generateCmd(from, to);
58 pipe[pipe_index] = popen(cmd, "r");
59 if (!pipe[pipe_index])
60 {
61 cerr << "Error executing command in RequestDispatcher::run()";
62 }
63 }
64 string result[PROXIES];
65 bool finished[PROXIES];
66 for (int pipe_index=0; pipe_index<count_pipes; pipe_index++)
67 {
68 finished[pipe_index] = false;
69 }
70 int count_finished = 0;
71 char* buffer;
72 size_t buffer_length=1024;
73 buffer = (char *) malloc (buffer_length + 1);
74 while (count_finished < count_pipes)
75 {
76 cout << "D\n";
77 fflush(stdout);
78 for(int pipe_index=0; pipe_index<count_pipes; ++pipe_index)
79 {
80 cout << "E\n";
81 fflush(stdout);
82 if (finished[pipe_index])
83 {
84 continue;
85 }
86 cout << "Getline" << buffer_length << "\n";
87 ssize_t bytes_read = getline(&buffer, &buffer_length, pipe[pipe_index]);
88 cout << "Getline Done ("<<bytes_read<< "," << buffer_length << ")\n";
89 fflush(stdout);
90 while (bytes_read>0)
91 {
92 for (int i=0; i<bytes_read; i++)
93 {
94 result[pipe_index] += buffer[i];
95 }
96 cout << "P\n";
97 fflush(stdout);
98 bytes_read = getline(&buffer, &buffer_length, pipe[pipe_index]);
99 cout << "Bytes read ("<<bytes_read<<","<< buffer_length << ")\n";
100 fflush(stdout);
101
102 }
103 if (bytes_read == -1) // then finished this pipe
104 {
105 string* r = &result[pipe_index];
106 //cout << *r;
107 finished[pipe_index] = true;
108 ++count_finished;
109 cout << "HI\n";
110 fflush(stdout);
111 // delete trailing '\0' from result
112 pclose(pipe[pipe_index]);
113 result[pipe_index] = result[pipe_index].substr(0, result[pipe_index].length()-1);
114 int pos = r->find("RESPONSE_DATA");
115 int valuepos, endvaluepos;
116 int request_index, length;
117 string headers;
118 int headerslength;
119 string body;
120 int bodypos, bodylength;
121 while (pos!=r->npos)
122 {
123 valuepos = r->find("REQUEST_INDEX=", pos) + 14;
124 endvaluepos = r->find("\n", valuepos);
125 request_index = pipe_index * per_proxy + atoi(r->substr(valuepos, endvaluepos-valuepos).c_str());
126
127 cout << "REQUEST_INDEX " << request_index;
128
129 valuepos = r->find("LENGTH=", pos) + 7;
130 endvaluepos = r->find("\n", valuepos);
131 length = atoi(r->substr(valuepos, endvaluepos-valuepos).c_str());
132
133 pos = r->find("START", pos)+5;
134 bodypos = r->find("\r\n\r\n", pos)+4;
135 headerslength = bodypos-pos-4;
136 bodylength = length-headerslength-4;
137 headers = r->substr(pos, headerslength);
138 body = r->substr(bodypos, bodylength);
139 request_info[request_index].response_receiver->notifyResponse(headers, body, request_index);
140
141 pos=r->find("RESPONSE_DATA", pos+length);
142 }
143 }
144 }
145 }
146 cout << "\n?\n";
147 fflush(stdout);
148 free(buffer);
149 request_info.clear();
150 }
151
152 const char* RequestDispatcher::generateCmd(int first_request, int to_request)
153 {
154 string r("/home/albert/apachebench-standalone-read-only/ab -a");
155 for (int i=first_request; i<to_request; i++)
156 {
157 r.append(" '");
158 r.append(request_info.at(i).request);
159 r.append("'");
160 }
161 ofstream out("/home/albert/apachebench-standalone-read-only/debug");
162 if(! out)
163 {
164 cerr<<"Cannot open output file\n";
165 return "";
166 }
167 out << r.c_str();
168 out.close();
169 return "/home/albert/apachebench-standalone-read-only/debug";
170 /*int size = strlen("/home/albert/apachebench-standalone-read-only/ab -a");
171 for (int i=first_request; i<to_request; i++)
172 {
173 size += 2+strlen(request_info.at(i).request)+1;
174 cout << "len: " << strlen(request_info.at(i).request) << "\n";
175 cout << "total: " << size << "\n";
176 }
177 size += 1;
178 char* cmd = new char[size];
179 strcpy(cmd, "/home/albert/apachebench-standalone-read-only/ab -a");
180 for (int i=first_request; i<to_request; i++)
181 {
182 cout << "LEN: " << strlen(cmd) << "\n";
183 cout << "NEXT: " << strlen(request_info.at(i).request) << "\n";
184 fflush(stdout);
185 strcat(cmd, " '");
186 strcat(cmd, request_info.at(i).request);
187 strcat(cmd, "'");
188 }
189 cout << "LEN: " << strlen(cmd) << "\n";
190 fflush(stdout);
191 return cmd;*/
192 }
When I run /home/albert/apachebench-standalone-read-only/debug from the command line everything works perfectly fine. It returns binary data.
The end of the output is:
P
Bytes read (272,6828)
P
Bytes read (42,6828)
P
Bytes read (464,6828)
P
Bytes read (195,6828)
P
Bytes read (355,6828)
P
Bytes read (69,6828)
P
Bytes read (111,6828)
P
Segmentation fault
Bytes read (368,6828)
P
Bytes read (-1,6828)
HI
REQUEST_INDEX 46REQUEST_INDEX 48REQUEST_INDEX 44REQUEST_INDEX 0REQUEST_INDEX 45
?
Mind the "?" for exiting the loop. After this, the program is finished.
By the way, I always thought the program would terminate on a segmentation fault (edit: I did not do anything to catch it).
In reply to some answers: There seem to be different versions of getline and I seem to be using the one documented here:
http://www.kernel.org/doc/man-pages/online/pages/man3/getline.3.html
So after some thought the issue I believe is that your buffer is being written to as you're reading it. In some cases the buffer is not done being written to and you remove some of the data from it (which could mean that you may read an empty buffer because the write isn't done). This is because you are using popen and simply piping data from another process. What I would recommend is that for one you use the C++ standard for getline (although both are somewhat unsafe) and that you have some leeway for reading data from the pipe. Retry logic might be what you need as I can't think of a clean way to solve this. If anyone knows please post it, I'm posting this because this is what I believe to be the likely culprit of the problem.
Also if you're coding in C++ I highly recommend that you use the C++ libraries so that you're not constantly mixing or casting between types (such as string to char * and such, it just saves you some hassle) and that you use the safer versions of methods so you avoid errors such as buffer overflows.