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.