Crea un compilador de FizzBuzz


17

Bienvenido al mundo del compilador de golf. Su tarea es escribir un programa que genere otro programa para reproducir una variante de FizzBuzz en las especificaciones.

Su compilador

Escriba un compilador que genere variantes del programa FizzBuzz según las especificaciones. La especificación de esta variante se expresa en forma de una matriz de pares enteros / cadenas.

  • La entrada puede ser de cualquier forma que sea conveniente para su idioma. (Mis ejemplos usan n: xxxx, pero esto es solo para fines ilustrativos).
  • Cada entrada entera solo puede usarse una vez por invocación de su compilador.
  • El entero de cada par tendrá un valor de al menos uno.
  • La cadena de cada par estará compuesta de solo cuatro letras ASCII exactamente.
  • El resultado debe ser un solo programa completo que cumpla con las siguientes reglas.
  • La salida puede estar en cualquier forma conveniente, siempre que sea un programa textual. (Entonces no hay expresiones lambda que regresen).

El comportamiento no está definido para las entradas que no se ajustan a las reglas anteriores.

Su programa generado de FizzBuzz

El programa generado por su compilador tomará un solo entero, n , como entrada. Producirá una secuencia de números comenzando desde uno hasta e incluyendo n , reemplazando los números con cadenas FizzBuzz cuando sea necesario.

  • El programa generado debe estar en el mismo idioma que el compilador.
  • La entrada n puede estar en cualquier forma conveniente para su idioma.
  • n tendrá un valor de al menos uno.
  • Un número que es un múltiplo de al menos uno de los enteros ingresados ​​al compilador debe ser reemplazado por todas las cadenas emparejadas con esos enteros unidos.
  • Un número que no debe ser reemplazado por una cadena FizzBuzz debe enviarse en ASCII decimal.

Por ejemplo;

> GenFizzBuzz 3:Fizz 5:Buzz
> a.out 5
1
2
Fizz
4
Buzz

Puntuación

Su entrada se puntuará según la duración de los programas que genera su compilador agregados a la duración de su compilador. Ejecute su compilador muchas veces con cada uno de los siguientes parámetros y agregue las longitudes de los programas generados junto con la longitud del compilador para encontrar su puntaje.

  1. Solo cuenta. (Sin entradas: el programa generado contará de 1 a n sin reemplazos).
  2. Solo golf. (1: Golf: el programa generado generará "Golf" n veces).
  3. FizzBuzz clásico. (3: Fizz, 5: Zumbido)

(Tenga en cuenta que se requiere que su compilador genere código para cualquier entrada válida, no solo estas enumeradas).


sin puntuación para la longitud del compilador?
Sparr

¿podemos suponer que los enteros son de un solo dígito? que no hay espacios en las cuerdas?
Sparr

@Sparr ¿Eso (enteros de dos dígitos) marcaría la diferencia? Recuerde, es solo el código generado lo que hace su puntaje.
billpg

bueno, fizzbuzz es un problema que ya se ha jugado muy a fondo en Internet. No sé si podría olvidar leer la solución si lo intentara.
Sparr

1
Finalmente, un desafío de golf que tiene sentido escribir en AWK.
shadowtalker

Respuestas:


8

Python 3 - 168 162 + 230 = 392

¡Oh, Python, te esfuerzas tanto, pero multiplicar las import sys;sys.argvcosas por 4 realmente duele!

import sys;a=eval(sys.argv[1])
print("import sys\nfor i in range(1,int(sys.argv[1])+1):print("+"+".join('"%s"*(i%%%d==0)'%t for t in a)+(a and"or str(i))"or"i)"))

Programas de salida:

import sys
for i in range(1,int(sys.argv[1])+1):print(i)
import sys
for i in range(1,int(sys.argv[1])+1):print("Golf"*(i%1==0)or str(i))
import sys
for i in range(1,int(sys.argv[1])+1):print("Fizz"*(i%3==0)+"Buzz"*(i%5==0)or str(i))
  • La entrada esperada para el programa principal es una secuencia evaluable de tuplas de Python o '()'para ninguna entrada. (Dijiste "conveniente".) Ejemplo de entrada: '()','("Golf",1),' , '("Fizz",3),("Buzz",5)'Nota citando para la cáscara y de salida para una entrada por comas.

  • Se corrigió el error de 1 a.m. al cambiar de dict (¡orden indefinido!) A tuplas.

  • La entrada esperada para los otros programas es solo el número


En su ejemplo de argumento de línea de comando, tuve que poner comillas dobles y usar comillas simples para 'Fizz' y 'Buzz', como '' {3: 'Fizz', 5: 'Buzz'} ", sin embargo, el programa todavía está arrojando un error para mí.
James Williams

Cual es el error?
Jason S

@ Jason: Hola. Estoy interesado en tu experiencia de este desafío. meta.codegolf.stackexchange.com/questions/5050/…
billpg

6

perl6 376 340 84 + 115 = 199

ACTUALIZACIÓN: cambió de perl5 a perl6 para quedarse saysin él use feature.

ACTUALIZACIÓN: tres casos de prueba en lugar de cinco

Hay cientos de soluciones ya desarrolladas para FizzBuzz, y muchos concursos terminan con el mismo resultado, así que ahí es donde comencé. Mi compilador solo produce una versión personalizada de esa solución. Se insertaron algunos caracteres adicionales para dar cuenta de la variación de "solo recuento".

compilador, espera argumentos como este: "Fizz 3" "Buzz 5"

print'say(('.(join'.',map{'('.(join')[$_%',split).']'}@ARGV).')||$_)for 1..$ARGV[0]'

programas compilados, espere un argumento así: 100

say(()||$_)for 1..$ARGV[0]
say(((Golf)[$_%1])||$_)for 1..$ARGV[0]
say(((Fizz)[$_%3].(Buzz)[$_%5])||$_)for 1..$ARGV[0]

Programas compilados para casos de prueba antiguos:

say(((Twoo)[$_%2].(Four)[$_%4].(Eiht)[$_%8])||$_)for 1..$ARGV[0]
say(((Twoo)[$_%2].(Thre)[$_%3].(Five)[$_%5].(Sevn)[$_%7])||$_)for 1..$ARGV[0]

He cambiado las reglas como se discutió en los comentarios de la pregunta. Querrás volver a calcular tu puntaje.
billpg

@billpg hecho y mejorado :)
Sparr

Hola. Estoy interesado en tu experiencia de este desafío. meta.codegolf.stackexchange.com/questions/5050/…
billpg

3

Pyth - 51 + (38 + 43 + 50) = 182 bytes

Probablemente puede golf el compilador de unos pocos bytes. Los enlaces en todos ellos son enlaces permanentes al intérprete en línea.

Compilador - 51 bytes

%"K[%s)=dc\"%s\"dFGr1hQJkFNKI!%%GN~J@dxKN))?JJG",zw

Simplemente formatea cadenas con una tupla de entrada. Toma datos como:

3 5
Fizz Buzz

Nada : 38 bytes

K[)=dc""dFGr1hQJkFNKI!%GN~J@dxKN))?JJG

Just Golf - 43 bytes

K[1)=dc"Golf"dFGr1hQJkFNKI!%GN~J@dxKN))?JJG

Classic Fizz Buzz - 50 bytes

K[3 5)=dc"Fizz Buzz"dFGr1hQJkFNKI!%GN~J@dxKN))?JJG

2

C ++ 11 ~ 486 + (234 + 244 + 255) = 1219

Primera participación aquí, este desafío no está entre los más difíciles, así que pensé en intentarlo. Sin embargo, usar C ++ e incluso con las adiciones de C ++ 11 sigue siendo un lenguaje bastante detallado, pero estoy seguro de que hay margen de mejora.

Compilador (486):

#include<sstream>
#include<iostream>
using namespace std;main(int c,char**v){stringstream t;int i;string s,o;o="#include <iostream>\n#include <map>\nusing namespace std;main(int c,char**v){int i,n=stoi(v[1]);map<int,string> f{";int z=2;for(int j=1;j<c;++j){t.str(v[j]);t.clear();t >> i; t >> s;o+="{"+to_string(i)+",\""+s+"\"}"+(z++==c?"":",");}o+= R"(};bool p;for(i=1;i<n;++i){p=true;for(auto e:f){if(i%e.first==0){cout<<e.second;p=false;}}cout<<(p?to_string(i):"")+"\n";}})";cout<<o;}

Asume argumentos en forma de 3Fizz 5Buzzetc.

Conde (234):

#include <iostream>
#include <map>
using namespace std;main(int c,char**v){int i,n=stoi(v[1]);map<int,string> f{};bool p;for(i=1;i<n;++i){p=true;for(auto e:f){if(i%e.first==0){cout<<e.second;p=false;}}cout<<(p?to_string(i):"")+"\n";}}

Golf (244):

#include <iostream>
#include <map>
using namespace std;main(int c,char**v){int i,n=stoi(v[1]);map<int,string> f{{1,"Golf"}};bool p;for(i=1;i<n;++i){p=true;for(auto e:f){if(i%e.first==0){cout<<e.second;p=false;}}cout<<(p?to_string(i):"")+"\n";}}

FizzBuzz (255):

#include <iostream>
#include <map>
using namespace std;main(int c,char**v){int i,n=stoi(v[1]);map<int,string> f{{3,"Fizz"},{5,"Buzz"}};bool p;for(i=1;i<n;++i){p=true;for(auto e:f){if(i%e.first==0){cout<<e.second;p=false;}}cout<<(p?to_string(i):"")+"\n";}}

Información Adicional

Probado con GCC 4.8.1, sin trampas del compilador.

Aquí hay un pequeño archivo MAKE para automatizar la generación de los casos de prueba y ejecutarlos (uso make run):

run:
    g++ main.cpp --std=c++11 -o fbc

    ./fbc > count.cpp
    g++ count.cpp --std=c++11
    echo "======= Count ========"
    ./a.out 15

    ./fbc 1Golf > golf.cpp
    g++ golf.cpp --std=c++11
    echo "======= Golf ========"
    ./a.out 15

    ./fbc 3Fizz 5Buzz > fizzbuzz.cpp
    g++ fizzbuzz.cpp --std=c++11
    echo "======= FizzBuzz ========"
    ./a.out 15

Hola. Estoy interesado en tu experiencia de este desafío. meta.codegolf.stackexchange.com/questions/5050/…
billpg

map<int,string> fpodría ser map<int,string>f. Podrías inicializar j=1al mismo tiempo con z.
Yytsi

2

Rubí 99 + (86 + 94 + 103) = 382

puts"(1..ARGV[0].to_i).each{|i|x=[];#{ARGV[0]}.each{|k,v|x<<v if i%k==0};puts x.size>0?x.join():i}"

Uso:

wc -c main.rb # 99 chars
ruby main.rb "{}" | ruby - 100 # 1..2..3..
ruby main.rb "{}" | wc -c # 86 chars
ruby main.rb "{1=>:Golf}" | ruby - 100 # Golf..Golf..Golf..
ruby main.rb "{1=>:Golf}" | wc -c # 94 chars
ruby main.rb "{3=>:Fizz,5=>:Buzz}" | ruby - 100 # 1..2..Fizz..4..Buzz..
ruby main.rb "{3=>:Fizz,5=>:Buzz}" | wc -c # 103 chars

2

Stax , 23 + 5 + 17 + 29 = 74

╥╟.└ç╘SJ∞CF╔v=▌╝Σ@∞ìé«g

Ejecutar y depurarlo

Respuesta más corta hasta el momento No sorprendentemente golpeado por Jelly. La plantilla de cadena proporcionada en Stax es realmente ordenada y proporciona funciones similares a printf. Los programas generados por el compilador son casi siempre tan cortos como el mejor que se puede lograr codificando manualmente, sin usar el empaque.

El compilador en sí tiene 23 bytes de longitud.

El equivalente ASCII es:

{H34|S_h"_`c%z`n?+"m"mz`cc_?

Entrada proporcionada [], genera este (5 bytes)

mzc_?

Ejecutar y depurarlo

Entrada proporcionada [[1,"Golf"]], genera este (17 bytes)

mz_1%z"Golf"?+c_?

Ejecutar y depurarlo

Entrada proporcionada [[3,"Fizz"],[5,"Buzz"]], genera este (29 bytes)

mz_3%z"Fizz"?+_5%z"Buzz"?+c_?

Ejecutar y depurarlo


1

Lisp común, 636 577

(ql:quickload'cl-ppcre)(lambda(z)(princ(subseq(ppcre:regex-replace-all" *([(')]) *"(with-output-to-string(@)(print`(lambda(n)(dotimes(i n)(loop for(m s)in ',z if(=(mod(1+ i)m)0)do(princ s))(do()((fresh-line))(princ (1+ i)))))@))"\\1")1)))

Tomé mi otra respuesta y la envolví en cuasiquotes mientras agregaba parámetros de entrada. Imprimo el formulario resultante como una sola línea y elimino los espacios en blanco innecesarios. El compilador es un poco más largo que la versión anterior, pero la puntuación resultante se reduce.

Puntuación

(let ((*standard-output* (make-broadcast-stream)))
  (loop
     for form in '(215                      ; Compiler
                   ()                       ; Count
                   ((1 "Golf"))             ; Golf
                   ((3 "Fizz")(5 "Buzz")))  ; FizzBuzz
     for length = (if (numberp form) form
                      (length (funcall *fun* form)))
     collect length into lengths
     sum length into sum
     finally (return (values sum lengths))))

Valores devueltos:

574
(215 111 119 129)

Bonito

(defun fizz-buzz-compiler (z)
  (princ (subseq
          (cl-ppcre:regex-replace-all
           " *([(')]) *"
           (with-output-to-string (stream)
             (print
              `(lambda (n)
                 (dotimes(i n)
                   (loop for (m s) in ',z
                      if (=(mod(1+ i)m)0)
                      do (princ s))
                   (do () ((fresh-line))
                     (princ (1+ i))))) stream))
             "\\1") 1)))

El formato de entrada es una lista de (number string)parejas. Por ejemplo:

(fizz-buzz-compiler '((3 "Fizz")(5 "Buzz")))

... imprime en salida estándar:

(LAMBDA(N)(DOTIMES(I N)(LOOP FOR(M S)IN'((3 "Fizz")(5 "Buzz"))IF(=(MOD(1+ I)M)0)DO(PRINC S))(DO NIL((FRESH-LINE))(PRINC(1+ I)))))

... que, muy bien impreso, es:

(lambda (n)
  (dotimes (i n)
    (loop for (m s) in '((3 "Fizz") (5 "Buzz"))
          if (= (mod (1+ i) m) 0)
          do (princ s))
    (do () ((fresh-line)) (princ (1+ i)))))

Prueba de la función resultante:

CL-USER> ((lambda (n)
  (dotimes (i n)
    (loop for (m s) in '((3 "Fizz") (5 "Buzz"))
          if (= (mod (1+ i) m) 0)
          do (princ s))
    (do () ((fresh-line)) (princ (1+ i))))) 20)
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz



0

C, 1080 bytes en total

Compilador [369 bytes]

#include<stdlib.h>
r,t,f=3,b=5,n;char*F="FIzz",*B="buZZ";main(int c,char **v){if(f)for(c=atoi(v[1]),n=1;c>=n;)r=f?n%f:0,r?(t=b?n%b:0)?printf("%i\n",n):puts(B):r?printf("%s%s\n",F,B):puts(F),++n;else for(c=0;c<atoi(v[1]);)printf("%i\n",++c);}

Zumbido burbujeante [241]

#include<stdlib.h>
r,t,f=3,b=5,n;char*F="FIzz",*B="buZZ";main(int c,char **v){if(f)for(c=atoi(v[1]),n=1;c>=n;)r=f?n%f:0,r?(t=b?n%b:0)?printf("%i\n",n):puts(B):r?printf("%s%s\n",F,B):puts(F),++n;else for(c=0;c<atoi(v[1]);)printf("%i\n",++c);}

Golf [237]

#include<stdlib.h>
r,t,f=1,b=0,n;char*F="golf",*B="";main(int c,char **v){if(f)for(c=atoi(v[1]),n=1;c>=n;)r=f?n%f:0,r?(t=b?n%b:0)?printf("%i\n",n):puts(B):r?printf("%s%s\n",F,B):puts(F),++n;else for(c=0;c<atoi(v[1]);)printf("%i\n",++c);}

Recuento [233 bytes]

#include<stdlib.h>
r,t,f=0,b=1,n;char*F="",*B="";main(int c,char **v){if(f)for(c=atoi(v[1]),n=1;c>=n;)r=f?n%f:0,r?(t=b?n%b:0)?printf("%i\n",n):puts(B):r?printf("%s%s\n",F,B):puts(F),++n;else for(c=0;c<atoi(v[1]);)printf("%i\n",++c);}

0

cc , 434 bytes

[:a]sa[91Pn93Pznlanps_znlanz0<R]sR[[[lj1-;aP1sb]sB0sj[dljd2+sj;a%0=Bljlz>F]sF[p2Q]sP]P]sI[[[]sF[pq]sP]nq]sN[z0=Nzn[sz]PlRxlIx]x[sn0dsb[1+0sjlFx[lb0=PAP]x0sbdln>M]dsMx]P

Pruébalo en línea!

La entrada para el compilador (168 bytes) debe colocarse en la pila como entero, cadena, entero, cadena, etc. ( 3 [Fizz] 5 [Buzz]). Debe darse en el orden en que uno quiere que se impriman sus efervescentes y zumbidos, lo que puede ser un poco engañoso (habiendo implementado la clasificación de burbujas endc antes, creo que me costaría alrededor de 100 bytes) pero también permite al usuario , digamos, todavía tengo 'Fizz' en 3 y 'Buzz' en 5, pero 15 'BuzzFizz'.

Estoy seguro de que esto se puede jugar un poco más; la macro principal en el programa final ( M) se basa en dos macros ( FyP ) que son bastante innecesarias dado que no hay entrada. En este momento, el compilador busca entradas y salidas de versiones diferentes (mucho más pequeñas) de estas macros si no hay ninguna, pero no estoy seguro de que toda la configuración sea óptima.

El compilador en sí es bastante sencillo, solo verifica si hay 'reglas' en la pila, y si es así, imprime el código que almacena la profundidad de la pila z, almacena la pila en una matriz indexada en 0 ay luego imprime la generalizada Código FizzBuzz. Si no había nada en la pila, realmente solo imprime una versión modificada del código FizzBuzz. Casos de prueba:

Sin entrada (46 bytes):

[]sF[pq]sPsn0dsb[1+0sjlFx[lb0=PAP]x0sbdln>M]dsMx

3 [Fizz] 5 [Zumbido] (117 bytes):

4sz[Buzz]3:a5
2:a[Fizz]1:a3
0:a[lj1-;aP1sb]sB0sj[dljd2+sj;a%0=Bljlz>F]sF[p2Q]sPsn0dsb[1+0sjlFx[lb0=PAP]x0sbdln>M]dsMx

1 [Golf] (103 bytes):

2sz[Golf]1:a1
0:a[lj1-;aP1sb]sB0sj[dljd2+sj;a%0=Bljlz>F]sF[p2Q]sPsn0dsb[1+0sjlFx[lb0=PAP]x0sbdln>M]dsMx

Todos esperan el valor n en la pila, esto se almacena en n. Los que tienen 'reglas' las colocan en la matriz a, con las cadenas en índices impares y los enteros en pares. La macro principal M, incrementa lo que esté en la pila, ejecuta una macro Fque verifica el valor contra la matriz a, comprueba si Festablece el registro ben verdadero o no e imprime la parte superior de la pila si es así o una nueva línea si no, se restablece ben falso, y luego mantiene ejecutándose si naún no se ha alcanzado. Macro F, dadas las reglas, recorre toda la matriz en busca de coincidencias. Se incrementa en dos ya que nuestros enteros y cadenas se entrelazan a través de la matriz, y en una coincidencia llama macro B. MacroBsolo recupera la cadena (posición actual en la matriz menos uno) y la imprime. También se pone ba la verdad. Nuestro compilador no se molesta en imprimir Bsin entrada, y esencialmente hace Fun nop.


0

vim, 122 (compilador) + 73 (vacío) + 90 (golf) + 123 (fizzbuzz) = 392 bytes

Compilador

:%s/\v(.*):(.*)/qq\1jA\2<C-V><C-V><C-V><ESC>q=@qgg
VgggJAddGdd:%s/\v[0-9]*([^0-9])/\1
<C-V><ESC>:%@n
:w
:so! %
<ESC>ggii%s/=/<C-V><ESC><C-V><C-A>a/g<C-V><ESC>"ncc:%!seq 0 =
<ESC>

Formato de entrada

3:Fizz
5:Buzz

Código generado para el caso FizzBuzz

i%s/=/<ESC><C-A>a/g<ESC>"ncc:%!seq 0 =
qq3jAFizz<C-V><ESC>q=@qggqq5jABuzz<C-V><ESC>q=@qggddGdd:%s/\v[0-9]*([^0-9])/\1
<ESC>:%@n
:w
:so! %

Código generado, anotado

# replace the input number with a regex that replaces the placeholder (=) 
# with the real number + 1 (we'll need an extra line as a terminator later)
i%s/=/<ESC><C-A>a/g<ESC>

# pull the substitution command into register c and enter insert mode
"ncc

# create the numbers 0..N+1
:%!seq 0 =

# for each word, scan down k lines at a time and append the word to each
qq3jAFizz<C-V><ESC>q=@qgg
qq5jABuzz<C-V><ESC>q=@qgg

# delete the 0 and N+1 lines
ddGdd

# remove the numbers from any line with words
:%s/\v[0-9]*([^0-9])/\1
<ESC>

# Run the command we created at the beginning, replacing the placeholder 
# with the real number
:%@n

# The file now contains yet another program, with the constants defined.   
# Save and run.
:w
:so! %

# The file now contains a program that, when run on a buffer containing 
# a single line with a number, will produce the appropriate output

<C-V>es 0x16. <ESC>es 0x1b. <C-A>es 0x01.

Sesión de ejemplo

$ cat code.txt
2:Foo
4:Bar
$ cat input.txt
8
$ { cat compile.vim; echo ':wq'; } | vim code.txt
# code.txt now contains the generated code
$ { cat code.txt; echo ':wq'; } | vim input.txt
$ cat input.txt
1
Foo
3
FooBar
5
Foo
7
FooBar

Algo extraño sucede cuando intento definir y ejecutar una macro desde otra macro. Si logro resolver eso, podría guardar algunos bytes sobre el enfoque de guardar y de origen.
Ray

-2

SlooSarksi .Lang, 179

%%--43^jjk"/][][0[#!#111# h SD G ergDFGdfg[]9--99+==

10
No estoy familiarizado con este lenguaje; ¿podría vincularnos a una página que lo describa?
lirtosiast
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.