While doing a college project I came upon the following problem: I have two maps (Kmer1 and Kmer2) which are composed by a string(key) and a int(value). I have to calculate the distance which follows this formula
[1-(I/U)]*100
Where...
...U = the sum of all int values inside Kmer1 U Kmer2
...I = the sum of all int values inside Kmer1 ∩ Kmer2
Consider that...
... The U and ∩ are made evaluating the keys (strings)
... When an element is in both maps:
- At the Union we add the one with higher int value
- At the Intersection we add the one with lower int value
Example:
Kmer1 = AAB¹ AAC¹ AAG³
Kmer2 = AAG¹ AAT² ABB¹
Union = AAB¹ AAC¹ AAG³ AAT² ABB¹ U= 8
Intersection = AAG¹ I= 1
Distance = 87.5
Code time! I've been trying to solve it but all solutions are like.. partially right, not all cases are covered. So when I tried to cover them, I ended in infinite loops, exceptions rising, long long nests of if-else (which were awfull..) anyway, here is the the least worse and non working try:
The setup:
Species::Kmer Kmer1, Kmer2; //The two following lines get the Kmer from another
Kmer1 = esp1->second.query_kmer(); //object.
Kmer2 = esp2->second.query_kmer();
Species::Kmer::const_iterator it1, it2, last1, last2;
it1 = Kmer1.cbegin(); //Both Kmer are maps, therefore they are ordered and
it2 = Kmer2.cbegin(); //whitout duplicates.
last1 = --Kmer1.cend();
last2 = --Kmer2.cend();
double U, I;
U = I = 0;
The loop where the formula is applied:
while (it1 != Kmer1.cend() and it2 != Kmer2.cend()){
if (it1->first == it2->first) {
if (it1->second > it2->second) {
U += it1->second;
I += it2->second;
} else {
U += it2->second;
I += it1->second;
}
++it1;
++it2;
} else if (it1->first < it2->first) {
U += it1->second;
++it1;
} else {
U += it2->second;
++it2;
}
}
Note that instead of first creating the Union and the intersection and then doing the total sum of each, I jumped directly to the sum of the values. I know maybe it's not that hard but I've been trying to solve it but I'm pretty much stuck...
I've uploaded the whole code at Github: (Maybe it helps)
- There is a makefile to build the code
- There is a file called input.txt with a sample for this specific problem
- Also inside the input.txt, after line13 (fin) I've added the expected output
- Executing ./program.exe < input.txt should be enough to test it.
https://github.com/PauGalopa/Cpp-Micro-Projects/tree/master/Release
IMPORTANT Yes! I'm aware of almost all the STL functionality that could do this in a few lines BUT... Since this is a college project i'm bound to the limitations of the sillabus so consider that I'm only allowed to use "map" "string" "vector" and a few more. No, I can't use "algorithm" (I really wish I could) I'll clarify any doubt about which things I can do or use in the coments.
Add these two loops just after your main while loop.
while (it1 != Kmer1.cend()){
U += it1->second;
it1++;
}
while (it2 != Kmer2.cend()){
U += it2->second;
it2++;
}