#include <iostream>
#include <string>
#include <cstdlib>
#include <boost/mpl/string.hpp>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/size_t.hpp>
using namespace std;
using namespace boost;
///////////////////////////////////////////////////////////////////////////////
// exponentiation calculations
template <int accum, int base, int exp> struct POWER_CORE : POWER_CORE<accum * base, base, exp - 1>{};
template <int accum, int base>
struct POWER_CORE<accum, base, 0>
{
enum : int { val = accum };
};
template <int base, int exp> struct POWER : POWER_CORE<1, base, exp>{};
///////////////////////////////////////////////////////////////////////////////
// # of digit calculations
template <int depth, unsigned int i> struct NUM_DIGITS_CORE : NUM_DIGITS_CORE<depth + 1, i / 10>{};
template <int depth>
struct NUM_DIGITS_CORE<depth, 0>
{
enum : int { val = depth};
};
template <int i> struct NUM_DIGITS : NUM_DIGITS_CORE<0, i>{};
template <>
struct NUM_DIGITS<0>
{
enum : int { val = 1 };
};
///////////////////////////////////////////////////////////////////////////////
// Convert digit to character (1 -> '1')
template <int i>
struct DIGIT_TO_CHAR
{
enum : char{ val = i + 48 };
};
///////////////////////////////////////////////////////////////////////////////
// Find the digit at a given offset into a number of the form 0000000017
template <unsigned int i, int place> // place -> [0 .. 10]
struct DIGIT_AT
{
enum : char{ val = (i / POWER<10, place>::val) % 10 };
};
struct NULL_CHAR
{
enum : char{ val = '\0' };
};
///////////////////////////////////////////////////////////////////////////////
// Convert the digit at a given offset into a number of the form '0000000017' to a character
template <unsigned int i, int place> // place -> [0 .. 9]
struct ALT_CHAR : DIGIT_TO_CHAR< DIGIT_AT<i, place>::val >{};
///////////////////////////////////////////////////////////////////////////////
// Convert the digit at a given offset into a number of the form '17' to a character
// Template description, with specialization to generate null characters for out of range offsets
template <unsigned int i, int offset, int numDigits, bool inRange>
struct OFFSET_CHAR_CORE_CHECKED{};
template <unsigned int i, int offset, int numDigits>
struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, false> : NULL_CHAR{};
template <unsigned int i, int offset, int numDigits>
struct OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, true> : ALT_CHAR<i, (numDigits - offset) - 1 >{};
// Perform the range check and pass it on
template <unsigned int i, int offset, int numDigits>
struct OFFSET_CHAR_CORE : OFFSET_CHAR_CORE_CHECKED<i, offset, numDigits, offset < numDigits>{};
// Calc the number of digits and pass it on
template <unsigned int i, int offset>
struct OFFSET_CHAR : OFFSET_CHAR_CORE<i, offset, NUM_DIGITS<i>::val>{};
///////////////////////////////////////////////////////////////////////////////
// Integer to char* template. Works on unsigned ints.
template <unsigned int i>
struct IntToStr
{
const static char str[];
typedef typename mpl::string<
OFFSET_CHAR<i, 0>::val,
OFFSET_CHAR<i, 1>::val,
OFFSET_CHAR<i, 2>::val,
OFFSET_CHAR<i, 3>::val,
OFFSET_CHAR<i, 4>::val,
OFFSET_CHAR<i, 5>::val,
/*OFFSET_CHAR<i, 6>::val,
OFFSET_CHAR<i, 7>::val,
OFFSET_CHAR<i, 8>::val,
OFFSET_CHAR<i, 9>::val,*/
NULL_CHAR::val>::type type;
};
template <unsigned int i>
const char IntToStr<i>::str[] =
{
OFFSET_CHAR<i, 0>::val,
OFFSET_CHAR<i, 1>::val,
OFFSET_CHAR<i, 2>::val,
OFFSET_CHAR<i, 3>::val,
OFFSET_CHAR<i, 4>::val,
OFFSET_CHAR<i, 5>::val,
OFFSET_CHAR<i, 6>::val,
OFFSET_CHAR<i, 7>::val,
OFFSET_CHAR<i, 8>::val,
OFFSET_CHAR<i, 9>::val,
NULL_CHAR::val
};
template <bool condition, class Then, class Else>
struct IF
{
typedef Then RET;
};
template <class Then, class Else>
struct IF<false, Then, Else>
{
typedef Else RET;
};
template < typename Str1, typename Str2 >
struct concat : mpl::insert_range<Str1, typename mpl::end<Str1>::type, Str2> {};
template <typename Str1, typename Str2, typename Str3 >
struct concat3 : mpl::insert_range<Str1, typename mpl::end<Str1>::type, typename concat<Str2, Str3 >::type > {};
typedef typename mpl::string<'f','i','z','z'>::type fizz;
typedef typename mpl::string<'b','u','z','z'>::type buzz;
typedef typename mpl::string<'\r', '\n'>::type mpendl;
typedef typename concat<fizz, buzz>::type fizzbuzz;
// discovered boost mpl limitation on some length
template <int N>
struct FizzBuzz
{
typedef typename concat3<typename FizzBuzz<N - 1>::type, typename IF<N % 15 == 0, typename fizzbuzz::type, typename IF<N % 3 == 0, typename fizz::type, typename IF<N % 5 == 0, typename buzz::type, typename IntToStr<N>::type >::RET >::RET >::RET, typename mpendl::type>::type type;
};
template <>
struct FizzBuzz<1>
{
typedef mpl::string<'1','\r','\n'>::type type;
};
int main(int argc, char** argv)
{
const int n = 7;
std::cout << mpl::c_str<FizzBuzz<n>::type>::value << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8c3RyaW5nPgojaW5jbHVkZSA8Y3N0ZGxpYj4KI2luY2x1ZGUgPGJvb3N0L21wbC9zdHJpbmcuaHBwPgojaW5jbHVkZSA8Ym9vc3QvbXBsL2ZvbGQuaHBwPgojaW5jbHVkZSA8Ym9vc3QvbXBsL3NpemVfdC5ocHA+CiAKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKdXNpbmcgbmFtZXNwYWNlIGJvb3N0OwogCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8gZXhwb25lbnRpYXRpb24gY2FsY3VsYXRpb25zCnRlbXBsYXRlIDxpbnQgYWNjdW0sIGludCBiYXNlLCBpbnQgZXhwPiBzdHJ1Y3QgUE9XRVJfQ09SRSA6IFBPV0VSX0NPUkU8YWNjdW0gKiBiYXNlLCBiYXNlLCBleHAgLSAxPnt9OwogCnRlbXBsYXRlIDxpbnQgYWNjdW0sIGludCBiYXNlPgpzdHJ1Y3QgUE9XRVJfQ09SRTxhY2N1bSwgYmFzZSwgMD4KewogICAgZW51bSA6IGludCB7IHZhbCA9IGFjY3VtIH07Cn07CiAKdGVtcGxhdGUgPGludCBiYXNlLCBpbnQgZXhwPiBzdHJ1Y3QgUE9XRVIgOiBQT1dFUl9DT1JFPDEsIGJhc2UsIGV4cD57fTsKIAovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vICMgb2YgZGlnaXQgY2FsY3VsYXRpb25zCnRlbXBsYXRlIDxpbnQgZGVwdGgsIHVuc2lnbmVkIGludCBpPiBzdHJ1Y3QgTlVNX0RJR0lUU19DT1JFIDogTlVNX0RJR0lUU19DT1JFPGRlcHRoICsgMSwgaSAvIDEwPnt9OwogCnRlbXBsYXRlIDxpbnQgZGVwdGg+CnN0cnVjdCBOVU1fRElHSVRTX0NPUkU8ZGVwdGgsIDA+CnsKICAgIGVudW0gOiBpbnQgeyB2YWwgPSBkZXB0aH07Cn07CiAKdGVtcGxhdGUgPGludCBpPiBzdHJ1Y3QgTlVNX0RJR0lUUyA6IE5VTV9ESUdJVFNfQ09SRTwwLCBpPnt9OwogCnRlbXBsYXRlIDw+CnN0cnVjdCBOVU1fRElHSVRTPDA+CnsKICAgIGVudW0gOiBpbnQgeyB2YWwgPSAxIH07Cn07CiAKLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLwovLyBDb252ZXJ0IGRpZ2l0IHRvIGNoYXJhY3RlciAoMSAtPiAnMScpCnRlbXBsYXRlIDxpbnQgaT4Kc3RydWN0IERJR0lUX1RPX0NIQVIKewogICAgZW51bSA6IGNoYXJ7IHZhbCA9IGkgKyA0OCB9Owp9OwogCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8gRmluZCB0aGUgZGlnaXQgYXQgYSBnaXZlbiBvZmZzZXQgaW50byBhIG51bWJlciBvZiB0aGUgZm9ybSAwMDAwMDAwMDE3CnRlbXBsYXRlIDx1bnNpZ25lZCBpbnQgaSwgaW50IHBsYWNlPiAvLyBwbGFjZSAtPiBbMCAuLiAxMF0Kc3RydWN0IERJR0lUX0FUCnsKICAgIGVudW0gOiBjaGFyeyB2YWwgPSAoaSAvIFBPV0VSPDEwLCBwbGFjZT46OnZhbCkgJSAxMCB9Owp9OwogCnN0cnVjdCBOVUxMX0NIQVIKewogICAgZW51bSA6IGNoYXJ7IHZhbCA9ICdcMCcgfTsKfTsKIAovLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vCi8vIENvbnZlcnQgdGhlIGRpZ2l0IGF0IGEgZ2l2ZW4gb2Zmc2V0IGludG8gYSBudW1iZXIgb2YgdGhlIGZvcm0gJzAwMDAwMDAwMTcnIHRvIGEgY2hhcmFjdGVyCnRlbXBsYXRlIDx1bnNpZ25lZCBpbnQgaSwgaW50IHBsYWNlPiAvLyBwbGFjZSAtPiBbMCAuLiA5XQogICAgc3RydWN0IEFMVF9DSEFSIDogRElHSVRfVE9fQ0hBUjwgRElHSVRfQVQ8aSwgcGxhY2U+Ojp2YWwgPnt9OwogCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8gQ29udmVydCB0aGUgZGlnaXQgYXQgYSBnaXZlbiBvZmZzZXQgaW50byBhIG51bWJlciBvZiB0aGUgZm9ybSAnMTcnIHRvIGEgY2hhcmFjdGVyCiAKLy8gVGVtcGxhdGUgZGVzY3JpcHRpb24sIHdpdGggc3BlY2lhbGl6YXRpb24gdG8gZ2VuZXJhdGUgbnVsbCBjaGFyYWN0ZXJzIGZvciBvdXQgb2YgcmFuZ2Ugb2Zmc2V0cwp0ZW1wbGF0ZSA8dW5zaWduZWQgaW50IGksIGludCBvZmZzZXQsIGludCBudW1EaWdpdHMsIGJvb2wgaW5SYW5nZT4gIAogICAgc3RydWN0IE9GRlNFVF9DSEFSX0NPUkVfQ0hFQ0tFRHt9Owp0ZW1wbGF0ZSA8dW5zaWduZWQgaW50IGksIGludCBvZmZzZXQsIGludCBudW1EaWdpdHM+ICAgICAgICAgICAgICAgIAogICAgc3RydWN0IE9GRlNFVF9DSEFSX0NPUkVfQ0hFQ0tFRDxpLCBvZmZzZXQsIG51bURpZ2l0cywgZmFsc2U+IDogTlVMTF9DSEFSe307CnRlbXBsYXRlIDx1bnNpZ25lZCBpbnQgaSwgaW50IG9mZnNldCwgaW50IG51bURpZ2l0cz4gICAgICAgICAgICAgICAgCiAgICBzdHJ1Y3QgT0ZGU0VUX0NIQVJfQ09SRV9DSEVDS0VEPGksIG9mZnNldCwgbnVtRGlnaXRzLCB0cnVlPiAgOiBBTFRfQ0hBUjxpLCAobnVtRGlnaXRzIC0gb2Zmc2V0KSAtIDEgPnt9OwogCi8vIFBlcmZvcm0gdGhlIHJhbmdlIGNoZWNrIGFuZCBwYXNzIGl0IG9uCnRlbXBsYXRlIDx1bnNpZ25lZCBpbnQgaSwgaW50IG9mZnNldCwgaW50IG51bURpZ2l0cz4KICAgIHN0cnVjdCBPRkZTRVRfQ0hBUl9DT1JFIDogT0ZGU0VUX0NIQVJfQ09SRV9DSEVDS0VEPGksIG9mZnNldCwgbnVtRGlnaXRzLCBvZmZzZXQgPCBudW1EaWdpdHM+e307CiAKLy8gQ2FsYyB0aGUgbnVtYmVyIG9mIGRpZ2l0cyBhbmQgcGFzcyBpdCBvbgp0ZW1wbGF0ZSA8dW5zaWduZWQgaW50IGksIGludCBvZmZzZXQ+CiAgICBzdHJ1Y3QgT0ZGU0VUX0NIQVIgOiBPRkZTRVRfQ0hBUl9DT1JFPGksIG9mZnNldCwgTlVNX0RJR0lUUzxpPjo6dmFsPnt9OwogCi8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8KLy8gSW50ZWdlciB0byBjaGFyKiB0ZW1wbGF0ZS4gV29ya3Mgb24gdW5zaWduZWQgaW50cy4KdGVtcGxhdGUgPHVuc2lnbmVkIGludCBpPgpzdHJ1Y3QgSW50VG9TdHIKewogICAgY29uc3Qgc3RhdGljIGNoYXIgc3RyW107CiAgICB0eXBlZGVmIHR5cGVuYW1lIG1wbDo6c3RyaW5nPAogICAgT0ZGU0VUX0NIQVI8aSwgMD46OnZhbCwKICAgIE9GRlNFVF9DSEFSPGksIDE+Ojp2YWwsCiAgICBPRkZTRVRfQ0hBUjxpLCAyPjo6dmFsLAogICAgT0ZGU0VUX0NIQVI8aSwgMz46OnZhbCwKICAgIE9GRlNFVF9DSEFSPGksIDQ+Ojp2YWwsCiAgICBPRkZTRVRfQ0hBUjxpLCA1Pjo6dmFsLAogICAgLypPRkZTRVRfQ0hBUjxpLCA2Pjo6dmFsLAogICAgT0ZGU0VUX0NIQVI8aSwgNz46OnZhbCwKICAgIE9GRlNFVF9DSEFSPGksIDg+Ojp2YWwsCiAgICBPRkZTRVRfQ0hBUjxpLCA5Pjo6dmFsLCovCiAgICBOVUxMX0NIQVI6OnZhbD46OnR5cGUgdHlwZTsKfTsKIAp0ZW1wbGF0ZSA8dW5zaWduZWQgaW50IGk+CmNvbnN0IGNoYXIgSW50VG9TdHI8aT46OnN0cltdID0gCnsKICAgIE9GRlNFVF9DSEFSPGksIDA+Ojp2YWwsCiAgICBPRkZTRVRfQ0hBUjxpLCAxPjo6dmFsLAogICAgT0ZGU0VUX0NIQVI8aSwgMj46OnZhbCwKICAgIE9GRlNFVF9DSEFSPGksIDM+Ojp2YWwsCiAgICBPRkZTRVRfQ0hBUjxpLCA0Pjo6dmFsLAogICAgT0ZGU0VUX0NIQVI8aSwgNT46OnZhbCwKICAgIE9GRlNFVF9DSEFSPGksIDY+Ojp2YWwsCiAgICBPRkZTRVRfQ0hBUjxpLCA3Pjo6dmFsLAogICAgT0ZGU0VUX0NIQVI8aSwgOD46OnZhbCwKICAgIE9GRlNFVF9DSEFSPGksIDk+Ojp2YWwsCiAgICBOVUxMX0NIQVI6OnZhbAp9OwogCnRlbXBsYXRlIDxib29sIGNvbmRpdGlvbiwgY2xhc3MgVGhlbiwgY2xhc3MgRWxzZT4Kc3RydWN0IElGCnsKICAgIHR5cGVkZWYgVGhlbiBSRVQ7Cn07CiAKdGVtcGxhdGUgPGNsYXNzIFRoZW4sIGNsYXNzIEVsc2U+CnN0cnVjdCBJRjxmYWxzZSwgVGhlbiwgRWxzZT4KewogICAgdHlwZWRlZiBFbHNlIFJFVDsKfTsKIAogCnRlbXBsYXRlIDwgdHlwZW5hbWUgU3RyMSwgdHlwZW5hbWUgU3RyMiA+CnN0cnVjdCBjb25jYXQgOiBtcGw6Omluc2VydF9yYW5nZTxTdHIxLCB0eXBlbmFtZSBtcGw6OmVuZDxTdHIxPjo6dHlwZSwgU3RyMj4ge307CnRlbXBsYXRlIDx0eXBlbmFtZSBTdHIxLCB0eXBlbmFtZSBTdHIyLCB0eXBlbmFtZSBTdHIzID4Kc3RydWN0IGNvbmNhdDMgOiBtcGw6Omluc2VydF9yYW5nZTxTdHIxLCB0eXBlbmFtZSBtcGw6OmVuZDxTdHIxPjo6dHlwZSwgdHlwZW5hbWUgY29uY2F0PFN0cjIsIFN0cjMgPjo6dHlwZSA+IHt9OwogCnR5cGVkZWYgdHlwZW5hbWUgbXBsOjpzdHJpbmc8J2YnLCdpJywneicsJ3onPjo6dHlwZSBmaXp6Owp0eXBlZGVmIHR5cGVuYW1lIG1wbDo6c3RyaW5nPCdiJywndScsJ3onLCd6Jz46OnR5cGUgYnV6ejsKdHlwZWRlZiB0eXBlbmFtZSBtcGw6OnN0cmluZzwnXHInLCAnXG4nPjo6dHlwZSBtcGVuZGw7CnR5cGVkZWYgdHlwZW5hbWUgY29uY2F0PGZpenosIGJ1eno+Ojp0eXBlIGZpenpidXp6OwogCi8vIGRpc2NvdmVyZWQgYm9vc3QgbXBsIGxpbWl0YXRpb24gb24gc29tZSBsZW5ndGgKIAp0ZW1wbGF0ZSA8aW50IE4+CnN0cnVjdCBGaXp6QnV6egp7CiAgICB0eXBlZGVmIHR5cGVuYW1lIGNvbmNhdDM8dHlwZW5hbWUgRml6ekJ1eno8TiAtIDE+Ojp0eXBlLCB0eXBlbmFtZSBJRjxOICUgMTUgPT0gMCwgdHlwZW5hbWUgZml6emJ1eno6OnR5cGUsIHR5cGVuYW1lIElGPE4gJSAzID09IDAsIHR5cGVuYW1lIGZpeno6OnR5cGUsIHR5cGVuYW1lIElGPE4gJSA1ID09IDAsIHR5cGVuYW1lIGJ1eno6OnR5cGUsIHR5cGVuYW1lIEludFRvU3RyPE4+Ojp0eXBlID46OlJFVCA+OjpSRVQgPjo6UkVULCB0eXBlbmFtZSBtcGVuZGw6OnR5cGU+Ojp0eXBlIHR5cGU7Cn07CiAKdGVtcGxhdGUgPD4Kc3RydWN0IEZpenpCdXp6PDE+CnsKICAgIHR5cGVkZWYgbXBsOjpzdHJpbmc8JzEnLCdccicsJ1xuJz46OnR5cGUgdHlwZTsKfTsKIAppbnQgbWFpbihpbnQgYXJnYywgY2hhcioqIGFyZ3YpCnsKICAgIGNvbnN0IGludCBuID0gNzsKICAgIHN0ZDo6Y291dCA8PCBtcGw6OmNfc3RyPEZpenpCdXp6PG4+Ojp0eXBlPjo6dmFsdWUgPDwgc3RkOjplbmRsOwoJcmV0dXJuIDA7Cn0=