fizz buzz in TMP [zamknięte]

10

Problem Fizz Buzz to bardzo podstawowy problem do rozwiązania, z którego korzystają niektórzy, aby wyeliminować rozmówców, którzy nie umieją programować. Problemem jest:

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

Celem tej modyfikacji problemu Fizz Buzz jest wykonanie powyższego algorytmu przy użyciu szablonów C ++, tak że potrzeba jak najmniejszej liczby operacji wykonawczych.

W razie potrzeby możesz zmniejszyć N do mniejszego zakresu, aby zmieścić się w obiektach TMP, jeśli to konieczne.

To nie powinno być „golfem”.


źródło
11
Należy powiedzieć „Szablon METAPROGRAMOWANIE” zamiast PZT, ponieważ większość ludzi-C ++ non miałoby żadnego pojęcia, co TMP.
Chris Jester-Young
6
„wyeliminowaliśmy rozmówców, którzy nie umieją programować”. Nie wiedziałem, że przeciętny programista musi znać szablonowe metaprogramowanie.
Alexandru
1
Jak definiujesz działanie środowiska wykonawczego? Instrukcja asemblera? Jeśli tak, dobrym pomysłem może być określenie kompilatora i platformy, aby nie było dwuznaczności.
sepp2k 27.01.11
7
@Alexandru: Powiedział, że problem fizzbuzz jest używany do „wyeliminowania ...”, nie że rozwiązanie problemu fizzbuzz przy użyciu Metaprogramowania szablonów jest.
sepp2k 27.01.11
1
Możliwy duplikat 1, 2, Fizz, 4, Buzz
pppery

Odpowiedzi:

3

Oto moja próba (leżał przez jakiś dzień, ponieważ nie byłem pewien, czy będzie to odpowiednie rozwiązanie). Zaskakująco, jedyny fragment, który wprowadziłem z @Chris, zmienił się template<int N, int m3, int m5>natemplate<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;
}

Dodatkowo, ponieważ jest to moja pierwsza próba TMP, wszelkie sugestie dotyczące ulepszenia mojego kodu będą mile widziane.

JPvdMerwe
źródło
2

Całkowicie nie golfowe rozwiązanie:

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";}
};

Przykładowy kod testowy:

#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
źródło
1

Okej, w końcu udało mi się spróbować. W przeciwieństwie do poprzednich rozwiązań moje rozwiązanie buduje cały ciąg wyjściowy w czasie kompilacji i wywołanie tylko run-time jest pojedynczy wywołanie cout„s <<operatora. Używam, boost::mplaby kod był w pewnym stopniu zarządzalny.

#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;
}

Niestety, kod będzie wysadzał się z boost::mpl::stringnarzekaniem na zbyt duże ciągi znaków, jeśli używasz nwięcej niż 9.

sepp2k
źródło
0

362 znaków.

#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;
}
efemeryczny
źródło
Chyba że coś mi umknie, wszystkie operacje odbywają się tutaj w czasie wykonywania.
sepp2k 30.10.11
@ sepp2k: Masz na myśli ?:? Myślałem, że można to ocenić podczas kompilacji. Oczywiście mam tutaj podczas runtime gigantyczną konkatenację strun.
efhemient
Przede wszystkim miałem na myśli budowę łańcucha i konkatenację, ale?: Również nie musi się zdarzyć w czasie kompilacji (choć prawdopodobnie tak będzie).
sepp2k 30.10.11
-2

lokalny b = io.read („* n”) lokalny i = 1 podczas gdy (i <= b) zrobić, jeśli i% 15 == 0 to wydrukować („FizzBuzz”) elseif i% 3 == 0 następnie wydrukować („Fizz „) elseif i% 5 == 0, a następnie wydrukuj („ Buzz ”) inaczej wydrukuj (i) koniec i = i + 1 koniec

juan diego grisales callejas
źródło
Witamy na stronie! Jaki to język? Możesz użyć formatowania kodu, podświetlając kod i klikając ikonę w edytorze.
Ad Hoc Garf Hunter
To pytanie dotyczy w szczególności FizzBuzz C++, a twoja odpowiedź to Lua (?). Czy miałeś na myśli zamieścić ogólne pytanie FizzBuzz ?
Jo King,