fizz buzz in TMP [chiuso]


10

Il problema di Fizz Buzz è un problema di base da risolvere che viene utilizzato da alcuni per eliminare gli intervistati che non sanno programmare. Il problema è:

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

Lo scopo di questa modifica del problema Fizz Buzz è quello di eseguire l'algoritmo sopra usando i template C ++ in modo che siano necessarie poche operazioni di runtime.

Se necessario, è possibile ridurre N a un intervallo inferiore per adattarlo agli oggetti TMP.

Questo non dovrebbe essere un "golf".


11
Si dovrebbe dire "Template Metaprogrammazione" piuttosto che TMP, perché la maggior parte la gente non-C ++ avrebbe alcuna idea di ciò che è TMP.
— Chris Jester-Young,

6
"estrai gli intervistati che non sanno programmare" Non sapevo che il programmatore medio avesse bisogno di conoscere la metaprogrammazione dei template.
— Alexandru,

1
Come si definisce l'operazione di runtime? Istruzioni assembler? In tal caso, potrebbe essere una buona idea specificare un compilatore e una piattaforma in modo che non ci siano ambiguità.
— sepp2k,

7
@Alexandru: Ha detto che il problema del fizzbuzz è usato per "estirpare ...", non che risolvere il problema del fizzbuzz usando Metaprogramming di Template sia.
— sepp2k,

1
Possibile duplicato di 1, 2, Fizz, 4, Buzz
— pppery il

Risposte:


3

Ecco il mio tentativo (l'ho tenuto in giro per un giorno o giù di lì, perché non ero sicuro che fosse adatto come soluzione). Sorprendentemente l'unico pezzo che ho incorporato da @Chris stava cambiando template<int N, int m3, int m5>intemplate<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;
}

Inoltre, poiché questo è il mio primo tentativo di TMP, qualsiasi suggerimento su come migliorare il mio codice sarebbe apprezzato.


2

Soluzione totalmente non golfizzata:

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

Codice di prova di esempio:

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

1

Okay, finalmente sono riuscito a provare. A differenza delle soluzioni precedenti la mia soluzione si basa l'intera stringa di uscita al momento della compilazione e la chiamata in fase di esecuzione è solo una singola chiamata a cout's <<dell'operatore. Sto usando boost::mplper mantenere il codice un po 'gestibile.

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

Purtroppo il codice esploderà boost::mpl::stringlamentandosi di stringhe troppo grandi quando si utilizza un valore nmaggiore di 9.


0

362 caratteri.

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

A meno che non mi manchi qualcosa, tutte le operazioni avvengono in fase di esecuzione qui.
— sepp2k,

@ sepp2k: vuoi dire ?:? Ho pensato che potesse essere valutato in fase di compilazione. Ovviamente, ho una concatenazione di stringhe giganti che si verifica in fase di esecuzione qui.
— effimero

Principalmente intendevo la costruzione della stringa e la concatenazione, ma anche il?: Non deve avvenire al momento della compilazione (anche se probabilmente lo farà).
— sepp2k,

-2

local b = io.read ("* n") local i = 1 mentre (i <= b) fa se i% 15 == 0 quindi stampa ("FizzBuzz") altrimenti se i% 3 == 0 quindi stampa ("Fizz ") elseif i% 5 == 0 quindi stampa (" Buzz ") else stampa (i) fine i = i + 1 fine


Benvenuti nel sito! Che lingua è questa? Puoi utilizzare la formattazione del codice evidenziando il codice e facendo clic sull'icona nell'editor.
— Ad Hoc Garf Hunter,

Questa domanda è specifica per FizzBuzz in C++e la tua risposta è in Lua (?). Intendevi pubblicare la domanda generica su FizzBuzz ?
— Jo King,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.