Reputation: 146
This solution looks ugly. I've tried to simplify using a vector and cycling a vector but would it be faster? I tried making up a formula to retrieve these numbers but I'm terrible at math!
if (SkillValue > 115 && SkillValue <= 135)
{
return 100 / 2;
}
else if (SkillValue > 135 && SkillValue <= 160)
{
return 100 / 3;
}
else if (SkillValue > 160 && SkillValue <= 190)
{
return 100 / 4;
}
else if (SkillValue > 190 && SkillValue <= 215)
{
return 100 / 5;
}
else if (SkillValue > 215 && SkillValue <= 295)
{
return 100 / 6;
}
else if (SkillValue > 295 && SkillValue <= 315)
{
return 100 / 9;
}
else if (SkillValue > 315 && SkillValue <= 355)
{
return 100 / 10;
}
else if (SkillValue > 355 && SkillValue <= 425)
{
return 100 / 11;
}
else if (SkillValue > 425 && SkillValue < 450)
{
return 100 / 12;
}
return 100;
}
Upvotes: 0
Views: 88
Reputation: 6131
It's hard to find an equation to compute your result because your ranges are not equal in size, and the divisor jumps at 295.
To make a more compact version, here's a way:
#include <algorithm>
#include <iterator>
// 296 repeats to compensate for the jump in your divisor
constexpr int ranges[] = {0, 115, 136, 161, 191, 216, 296, 296, 296, 316, 356, 426, 456};
int compute(int SkillValue) {
if (SkillValue <= 115 or SkillValue >= 450) {
return 100;
}
auto elt = std::upper_bound(std::begin(ranges), std::end(ranges), SkillValue);
return 100 / (elt == std::end(ranges) ? 1 : elt - std::begin(ranges));
}
This computes the same output as your original function, but I can't actually say I like it any better.
Using a map, it's a little easier to read:
#include <map>
const std::map<int,int> ranges {
{115, 1},
{135, 2},
{160, 3},
{190, 4},
{215, 5},
{295, 6},
{315, 9},
{355, 10},
{425, 11},
{450, 12}
};
int compute(int SkillValue) {
if (SkillValue <= 115 or SkillValue >= 450) return 100;
auto elt = ranges.upper_bound(SkillValue-1);
return 100 / (elt == std::end(ranges) ? 1 : elt->second);
}
Upvotes: 1
Reputation: 60228
There doesn't appear to be any pattern to the bounds for each if
condition, or at least any pattern that would let you write this as a closed form check.
However, you are currently checking all the if
conditions, which is O(n)
where n
is the number of conditions. You can do this in O(log(n))
by using std::lower_bound
on a range to find the value of the denominator, like this:
std::array bounds { 115, 135, 160, 190, ... };
std::array dens {1, 2, 3, 4, ... , 1}; // extra 1 at the end to account for the
// case that none of the bounds match
auto it = std::lower_bound(std::begin(bounds), std::end(bounds), SkillValue);
return 100 / dens[std::distance(std::begin(bounds), it)];
Upvotes: 2
Reputation: 17902
Right off the bat, you are repeating logic in each conditional that can be refactored out of the previous conditionals by switching to the following form:
if (SkillValue <= 115) {
return 100/1;
} else if (SkillValue <= 135) {// the 'else' explicitly means that it is already NOT <= 115, aka IS > 115, so no need to repeat with a '&&'
return 100/2;
} else if (SkillValue <= 160) {
return 100/3;
} else if (SkillValue <= 190) {
return 100/4;
}//... and so on
Upvotes: 2