fizz buzz in TMP

10

1

The Fizz Buzz problem is a very basic problem to solve that is used by some to weed out interviewees that don't know how to program. The problem is:

Set N = [0,100]
Set F = x in N where x % 3 == 0
Set B = x in N where x % 5 == 0
Set FB = F intersect B

For all N:
  if x in F: print fizz
  if x in B: print buzz
  if x in FB: print fizzbuzz
  if x not in F|B|FB print x

The object of this modification of the Fizz Buzz problem is to perform the above algorithm using C++ templates such that as few runtime operations are necessary as can be done.

You can reduce N to a smaller range if you need to in order to fit within TMP objects where necessary.

This isn't expected to be a "golf".

user50

Posted 2011-01-27T21:43:42.670

Reputation:

Question was closed 2019-12-24T11:47:22.213

11You should say "Template Metaprogramming" rather than TMP, because most non-C++ people would have no idea what TMP is. – Chris Jester-Young – 2011-01-27T21:47:51.787

6"weed out interviewees that don't know how to program" I didn't know that the average programmer needs to know Template Metaprogramming. – Alexandru – 2011-01-27T21:51:53.053

1How do you define runtime operation? Assembler instruction? If so it might be a good idea to specify a compiler and platform so that there's no ambiguity. – sepp2k – 2011-01-27T21:53:07.507

Backing up ChrisJester-Young: Imo TMP is temporary; template is TPL. – Titus – 2017-02-12T14:53:41.383

7@Alexandru: He said that the fizzbuzz problem is used to "weed out...", not that solving the fizzbuzz problem using Template Metaprogramming is. – sepp2k – 2011-01-27T22:19:51.040

Maybe you should mention that for all other numbers you need to print the number? – JPvdMerwe – 2011-01-27T22:36:30.027

1

Possible duplicate of 1, 2, Fizz, 4, Buzz

– pppery – 2019-12-23T05:09:54.753

Answers

3

Here's my attempt (had it lying around for a day or so, because I was unsure whether it was fit as a solution). Surprisingly the only bit I incorporated from @Chris was changing template<int N, int m3, int m5> to template<int N, int m3=N%3, int m5=N%5>

#include <iostream>

using namespace std;

template<int N, int m3=N%3, int m5=N%5>
struct fizzbuzz_print {
  static void print() {
    cout << N << '\n';
  }
};

template<int N, int m5>
struct fizzbuzz_print<N, 0, m5> {
  static void print() {
    cout << "fizz\n";
  }
};

template<int N, int m3>
struct fizzbuzz_print<N, m3, 0> {
  static void print() {
    cout << "buzz\n";
  }
};

template<int N>
struct fizzbuzz_print<N, 0, 0> {
  static void print() {
    cout << "fizzbuzz\n";
  }
};

template<int N>
struct fizzbuzz:public fizzbuzz<N-1> {
  fizzbuzz<N>() {
    fizzbuzz_print<N>::print();
  }
};

template<>
struct fizzbuzz<1> {
  fizzbuzz<1>() {
    fizzbuzz_print<1>::print();
  }
};

int main() {
  fizzbuzz<100> t;
}

Additionally, since this is my first attempt at TMP, any suggestions on improving my code would be appreciated.

JPvdMerwe

Posted 2011-01-27T21:43:42.670

Reputation: 2 565

2

Totally non-golfed solution:

template <int n, int m3 = n % 3, int m5 = n % 5>
struct FizzBuzz {
    static int value() {return n;}
};

template <int n, int m5>
struct FizzBuzz<n, 0, m5> {
    static char const* value() {return "Fizz";}
};

template <int n, int m3>
struct FizzBuzz<n, m3, 0> {
    static char const* value() {return "Buzz";}
};

template <int n>
struct FizzBuzz<n, 0, 0> {
    static char const* value() {return "FizzBuzz";}
};

Sample test code:

#include <iostream>

int
main()
{
    std::cout << FizzBuzz<1>::value() << '\n'
              << FizzBuzz<2>::value() << '\n'
              << FizzBuzz<3>::value() << '\n'
              << FizzBuzz<4>::value() << '\n'
              << FizzBuzz<5>::value() << '\n'
              << FizzBuzz<13>::value() << '\n'
              << FizzBuzz<14>::value() << '\n'
              << FizzBuzz<15>::value() << '\n'
              << FizzBuzz<16>::value() << '\n';
}

Chris Jester-Young

Posted 2011-01-27T21:43:42.670

Reputation: 4 464

1

Okay, I finally got around to taking a shot at this. Unlike the previous solutions my solution builds the entire output string at compile time and the only run-time call is a single call to cout's << operator. I'm using boost::mpl to keep the code somewhat manageable.

#include <boost/mpl/string.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/char.hpp>
#include <boost/mpl/if.hpp>

using namespace boost::mpl;
using std::cout;

template<int n> struct IntToString {
    typedef typename push_back<typename IntToString<n/10>::str, char_<'0'+n%10> >::type str;
};


template<> struct IntToString<0> {
    typedef string<> str;
};


template<int n> struct FizzBuzzHelper {
    typedef typename push_back<typename IntToString<n>::str, char_<'\n'> >::type intstring;
    typedef typename if_< bool_<n%15==0>, string<'fizz','buzz','\n'>,
                          typename if_< bool_<n%5==0>, string<'buzz','\n'>,
                                        typename if_< bool_<n%3==0>, string<'fizz','\n'>,
                                                      intstring>::type >::type >::type str;
};

template<int n> struct FizzBuzz {
    typedef typename insert_range<typename FizzBuzz<n-1>::str,
                                  typename end<typename FizzBuzz<n-1>::str>::type,
                                  typename FizzBuzzHelper<n>::str>::type str;
};

template<> struct FizzBuzz<0> {
    typedef string<> str;
};


#include <iostream>

int main() {
    cout << c_str<FizzBuzz<9>::str>::value;
    return 0;
}

Sadly the code will blow up with boost::mpl::string complaining about too-large strings when using any n greater than 9.

sepp2k

Posted 2011-01-27T21:43:42.670

Reputation: 1 679

0

362 characters.

#include <iostream>
#include <string>

using namespace std;

template<int N>
struct S {
    static string s, f, l;
};

template<int N>
string S<N>::s =
    N > 9
      ? S<N / 10>::s + S<N % 10>::s
      : string(1, '0' + N);

template<int N>
string S<N>::f =
    N % 15
      ? N % 5
          ? N % 3
              ? s
              : "fizz"
          : "buzz"
      : "fizzbuzz";

template<>
string S<0>::l = f;
template<int N>
string S<N>::l = S<N - 1>::l + "\n" + f;

int main() {
    cout << S<100>::l << endl;
    return 0;
}

ephemient

Posted 2011-01-27T21:43:42.670

Reputation: 1 601

Unless I'm missing something all of the operations happen at run time here. – sepp2k – 2011-10-30T19:02:53.227

@sepp2k: Do you mean ?:? I thought that could be evaluated at compile time. Of course, I do have a giant string concatenation happening at runtime here. – ephemient – 2011-10-30T19:51:54.570

Primarily I meant the string construction and concatenation, but the ?: also doesn't have to happen at compile time (though it probably will). – sepp2k – 2011-10-30T21:16:45.527

-2

local b=io.read("*n") local i=1 while(i<=b) do if i % 15 == 0 then print("FizzBuzz") elseif i % 3 == 0 then print("Fizz") elseif i % 5 == 0 then print("Buzz") else print(i) end i=i+1 end

juan diego grisales callejas

Posted 2011-01-27T21:43:42.670

Reputation: 1

Welcome to the site! What language is this? You can use code formatting by highlighting your code and clicking the icon in the editor. – Post Rock Garf Hunter – 2019-12-19T16:31:51.393

This question is specifically for FizzBuzz in C++, and your answer is in Lua (?). Did you mean to post to the generic FizzBuzz question?

– Jo King – 2019-12-19T21:46:34.687