I think you are using the wrong map
to solve your problem.
Let's say there are three children that have 1kg chocolate. If I understand you correctly, you want to divide 1kg amongst the three. This leads me to think that key to the map is 1kg
and it should map to a set of three children.
std::map<double, std::set<ChildInfo>>
Using a double
for key is tricky since the comparison is not as reliable as comparison of integral types. You can use a custom compare function that tests the numbers within a certain tolerance.
Here's a working program:
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
using namespace std;
struct ChildInfo
{
int id;
double gram;
};
// Custom functor to compare doubles.
struct DoubleCompare
{
bool operator()(double x1, double x2)
{
static double tolerance = 1.0E-10; // Pick something else if this doesn't work.
// If the numbers are almost equal.
return ( fabs(x2-x1) > tolerance && x1 < x2);
}
};
// Function to compare two ChildInfo to insert them into a set.
bool operator < (const ChildInfo& lhs, const ChildInfo& rhs) { return lhs.id < rhs.id; }
std::ostream& operator<<(std::ostream& str, const ChildInfo& ci) {
str << " " << ci.id << " gram " << ci.gram << "\n";
return str;
}
// Read the info for one child.
void input(vector<ChildInfo> &v)
{
ChildInfo newInfo;
cin >> newInfo.id >> newInfo.gram;
v.push_back(newInfo);
}
// Compute the mapped info from the vector of ChildInfo
void computeMappedInfo(vector<ChildInfo> const& vinfo,
std::map<double, std::set<ChildInfo>, DoubleCompare>& mappedInfo)
{
// Separate them into sets first.
for ( ChildInfo const& info : vinfo )
{
mappedInfo[info.gram].insert(info);
}
// Divide the grams in the set.
for ( auto& item : mappedInfo )
{
// The set can't be changed in place.
// Create a new set and replace the old set with the new set.
std::set<ChildInfo> newSet;
size_t s = item.second.size();
for ( auto info : item.second )
{
info.gram /= s;
newSet.insert(info);
}
mappedInfo[item.first] = newSet;
}
}
// Display the mapped info.
void display(std::map<double, std::set<ChildInfo>, DoubleCompare> const& mappedInfo)
{
for ( auto const& item : mappedInfo )
{
for ( auto& info : item.second )
{
std::cout << info << std::endl;
}
}
}
int main()
{
int childNum = 0;
cin >> childNum;
std::vector <ChildInfo> info;
for (int i = 0; i < childNum; ++i) {
input(info);
}
std::map<double, std::set<ChildInfo>, DoubleCompare> mappedInfo;
computeMappedInfo(info, mappedInfo);
display(mappedInfo);
return 0;
}
Input:
8
1 1000
2 1000
3 1000
4 500
5 600
7 800
8 800
Output:
4 gram 500
5 gram 600
7 gram 400
8 gram 400
1 gram 333.333
2 gram 333.333
3 gram 333.333
See it working at http://ideone.com/Nq5XBH.