Here are some things that may help you improve your program. First, I'll mention a few things about the code you've already written, and then I'll describe an idea for a better algorithm.
Be careful with signed versus unsigned
By the problem description, neither start nor end can be less than 1, so they should probably be declared as unsigned rather than int.
Isolate calculation from I/O
The main routine does both the input and output and also is materially involved in the main calculation. I'd advocate that that function should be isolated like this:
int segcount(unsigned start, unsigned end) { unsigned sum = 0; for(auto i = start; i <= end; ++i) { std::string current_num = std::to_string(i); for(auto c: current_num) { sum += get_number_of_segments(c); } } return sum; } int main() { unsigned start, end; std::cin >> start >> end; auto sum = segcount(start, end); std::cout << sum << '\n'; }
Use const where practical
The segment_count map shouldn't be changed once constructed, and so it should be declared const.
Avoid global variables
The segment_count variable is only used within get_number_of_segments(), so it should go there instead of being a global. I would also avoid the overhead of the std::unordered_map by using a simple array:
unsigned get_number_of_segments(char num) { static constexpr std::array<unsigned, 10> segment_count{ 6, 2, 5, 5, 4, 5, 6, 3, 7, 6 }; return segment_count[num-'0']; }
A better algorithm
Your existing code, while not the fastest possible, does have a significant advantage in that it is obviously correct. We can use that to verify any alternative approach as well as using it for timing comparisons. From here to the end of this review, I'll be showing stepwise improvements in the code.
Write a test harness
We might write several versions of the code and want to compare them. One nice way to do that is using a templated structure and a macro like this:
template <typename F> struct testfunc { F *fn; const char *name; }; #define TEST(x) { x, #x }
Now we can easily make an array of tests and run through all alternative algorithms:
#include "stopwatch.h" int main() { const testfunc<decltype(segcount)> test[]{ TEST(segcount), TEST(segcount2), }; unsigned start, end, sum; std::cin >> start >> end; for (const auto t : test) { Stopwatch<std::chrono::milliseconds> sw; sum = t.fn(start, end); std::cout << t.name << ": " << sum << ", " << sw.stop() << "ms\n"; } }
Note that this uses my Stopwatch template, but one could use an alternative if desired.
Think carefully about the problem
First, let's consider a range of single digit numbers. If we go from 1 to 5, for example, we simply add up the segment counts for each of those digits \$= 2+5+5+4+5 = 21\$. For a range that doesn't start from 1, such as for 3 to 5, we can calculate it one of two ways. We could calculate just for those numbers \$= 5+4+5 = 14\$ or we could calculate 1 to 5 and subtract 1 to 2. The motivation for doing it by the latter method is that we can precalculate all possible ranges for a digit and then simply do two lookups and a subtraction.
We can now extend this to look at two-digit numbers. If we have a range in which the first digit doesn't change, such as 71 to 75 it's simply the single digit range 1 to 5 (which we already calculated above is 21) plus the size of the range (5) times the segments for the first digit (3), so the answer is \$21 + 5(3) = 36\$.
If it's a two-digit number for which the first digit does change, we can break it down into a sum of two-digit ranges for which the leading digit is constant. For example, if we go from 71 to 88, we can consider it as two subranges: 71 to 79 and 80 to 88 where the algorithm above could be applied.
I think you can probably take it from there and see how to extend the algorithm generically.