zumbido fizz en TMP [cerrado]

10

El problema de Fizz Buzz es un problema muy básico para resolver que algunos usan para descartar a los entrevistados que no saben programar. El problema es:

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

El objetivo de esta modificación del problema de Fizz Buzz es realizar el algoritmo anterior utilizando plantillas de C ++ de modo que se necesiten tan pocas operaciones de tiempo de ejecución como se pueda hacer.

Puede reducir N a un rango más pequeño si es necesario para que quepa dentro de los objetos TMP cuando sea necesario.

No se espera que sea un "golf".


fuente
11
Que debe decir "Plantilla Metaprogramación" en lugar de TMP, porque la mayoría de la gente no-C ++ tendrían ninguna idea de lo que es TMP.
Chris Jester-Young
66
"eliminar a los entrevistados que no saben programar" No sabía que el programador promedio necesita conocer la Metaprogramación de plantillas.
Alexandru
1
¿Cómo define la operación en tiempo de ejecución? Instrucciones de ensamblador? Si es así, podría ser una buena idea especificar un compilador y una plataforma para que no haya ambigüedad.
sepp2k
77
@Alexandru: Dijo que el problema de fizzbuzz se usa para "eliminar ...", no que lo es resolver el problema de fizzbuzz usando la Metaprogramación de plantillas.
sepp2k
1
Posible duplicado de 1, 2, Fizz, 4, Buzz
pppery

Respuestas:

3

Aquí está mi intento (lo tuve por un día más o menos, porque no estaba seguro de si era una solución adecuada). Sorprendentemente, lo único que incorporé de @Chris fue cambiar template<int N, int m3, int m5>atemplate<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;
}

Además, dado que este es mi primer intento en TMP, agradecería cualquier sugerencia para mejorar mi código.

JPvdMerwe
fuente
2

Solución totalmente no golfizada:

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

Código de prueba de muestra:

#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
fuente
1

Bien, finalmente pude intentarlo. A diferencia de las soluciones anteriores mi solución se basa toda la cadena de salida en tiempo de compilación y la llamada en tiempo de ejecución es solamente una sola llamada a cout's <<operador. Estoy usando boost::mplpara mantener el código algo manejable.

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

Lamentablemente, el código explotará al boost::mpl::stringquejarse de cadenas demasiado grandes cuando se usa nmás de 9.

sepp2k
fuente
0

362 caracteres.

#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;
}
efímero
fuente
A menos que me falte algo, todas las operaciones suceden en tiempo de ejecución aquí.
sepp2k
@ sepp2k: ¿Quieres decir ?:? Pensé que podría evaluarse en tiempo de compilación. Por supuesto, aquí tengo una concatenación de cuerdas gigantes en tiempo de ejecución.
Ephemient
Principalmente me refería a la construcción de cadenas y la concatenación, pero el?: Tampoco tiene que suceder en el momento de la compilación (aunque probablemente lo hará).
sepp2k
-2

local b = io.read ("* n") local i = 1 mientras que (i <= b) si i% 15 == 0 luego imprime ("FizzBuzz") si i% 3 == 0 luego imprime ("Fizz ") elseif i% 5 == 0 luego print (" Buzz ") más print (i) end i = i + 1 end

juan diego grisales callejas
fuente
Bienvenido al sitio! ¿Qué lenguaje es este? Puede usar el formato de código resaltando su código y haciendo clic en el icono en el editor.
Ad Hoc Garf Hunter
Esta pregunta es específicamente para FizzBuzz C++, y su respuesta está en Lua (?). ¿Querías publicar en la pregunta genérica de FizzBuzz ?
Jo King