My exercise is to write the Fizz Buzz problem with the following in mind:
- Use the latest up-to-date style and best practices for a C++17 compiler.
- Don’t just show that I can write a loop. Rather, illustrate some good engineering concepts, as much as can be done without making the code not-so-trivial.
The “good engineering” shown is
to separate the logic from I/O. The code does something, and is called by a UI of some kind or a test case checker. Most (all?) solutions I see of this simply print to standard output in the middle of the logic.
Don’t repeat blocks of code where only a couple values change. Instead, store the values and loop over them.
Be mindful of future enhancements (code always gets more complex over time) and localization.
I think I was successful in that point 2 makes the code simpler and shorter. Implementing point 1 seems to be free — appending vs outputting, same thing.
#include <utility>
#include <iostream>
#include <boost/range/irange.hpp>
using std::string;
constexpr std::pair<int, const char*> fbchart[]{
{ 3, "Fizz" }, { 5, "Buzz" }, // standard FizzBuzz
{ 7, "Boom" } // easily generalized and extended by adding to this chart!
};
// Game Impl 1 : Simple stateless function
string fbencode (int n)
{
string retval;
for (auto&[div, codeword] : fbchart) {
if ((n%div)==0) retval += codeword;
}
if (retval.empty()) retval= std::to_string(n);
return retval;
}
// and to drive it:
int main() {
using boost::irange;
for (auto n : irange(1,101)) {
cout << n << ": " << fbencode(n) << '\n';
}
}
In the main
, I avoided a legacy for
-loop by using Boost.Range 2.0. That is tried and true for production work. I’ve not tried to get the latest Visual Studio compiler drop to swallow Range-v3 yet.