Crea un compilatore FizzBuzz


17

Benvenuti nel mondo del golf del compilatore. Il tuo compito è quello di scrivere un programma che genera un altro programma per riprodurre una variante di FizzBuzz su specifica.

Il tuo compilatore

Scrivi un compilatore che genera varianti del programma FizzBuzz su specifica. Le specifiche di questa variante sono espresse sotto forma di un array di coppie numero intero / stringa.

  • L'input può essere in qualsiasi forma che sia conveniente per la tua lingua. (I miei esempi usano n: xxxx, ma questo è solo a scopo illustrativo.)
  • Ogni input intero può essere utilizzato solo una volta per invocazione del compilatore.
  • L'intero di ciascuna coppia avrà un valore di almeno uno.
  • La stringa di ciascuna coppia sarà composta solo da esattamente quattro lettere ASCII.
  • L'output deve essere un singolo programma completo conforme alle regole seguenti.
  • L'output può essere in qualsiasi forma conveniente, purché si tratti di un programma testuale. (Quindi non restituire espressioni lambda.)

Il comportamento non è definito per gli input non conformi alle regole precedenti.

Il tuo programma FizzBuzz generato

Il programma generato dal tuo compilatore prenderà un singolo intero, n , come input. Produrrà una sequenza di numeri a partire da uno fino a incluso n , sostituendo i numeri con stringhe FizzBuzz quando richiesto.

  • Il programma generato deve essere nella stessa lingua del compilatore.
  • L'ingresso n può essere in qualsiasi forma conveniente per la tua lingua.
  • n avrà un valore di almeno uno.
  • Un numero che è un multiplo di almeno uno degli interi immessi nel compilatore deve essere sostituito da tutte le stringhe accoppiate con quegli interi uniti.
  • Un numero che non deve essere sostituito da una stringa FizzBuzz deve essere emesso in ASCII decimale.

Per esempio;

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

punteggio

La tua voce verrà valutata in base alla lunghezza dei programmi generati dal tuo compilatore aggiunti alla lunghezza del tuo compilatore. Esegui il tuo compilatore molte volte con ciascuno dei seguenti parametri e aggiungi le lunghezze dei programmi generati insieme alla lunghezza del compilatore per trovare il tuo punteggio.

  1. Conta e basta. (Nessun input: il programma generato conterà da 1 a n senza sostituzioni.)
  2. Solo golf. (1: Golf - Il programma generato genererà "Golf" n volte.)
  3. FizzBuzz classica. (3: Fizz, 5: Buzz)

(Nota che il tuo compilatore è tenuto a generare codice per qualsiasi input valido, non solo questi elencati.)


nessun punteggio per la lunghezza del compilatore ??
Sparr,

possiamo supporre che gli interi siano a una cifra? che non ci sono spazi nelle stringhe?
Sparr,

@Sparr Che (numeri interi a due cifre) farebbe la differenza? Ricorda, è solo il codice generato che fa il tuo punteggio.
billpg,

bene, fizzbuzz è un problema già estremamente approfondito altrove su Internet. Non so se potrei dimenticare di leggere la soluzione se ci provassi.
Sparr,

1
Finalmente una sfida di golf che in realtà ha senso scrivere in AWK.
Shadowtalker,

Risposte:


8

Python 3 - 168 162 + 230 = 392

Oh, Python, ci provi così tanto, ma moltiplicare le import sys;sys.argvcose per 4 fa davvero male!

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)"))

Programmi di output:

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))
  • L'input previsto per il programma principale è una sequenza valutabile di tuple Python o '()'per nessun input. (Hai detto "comoda".) Ingresso Esempio: '()', '("Golf",1),', '("Fizz",3),("Buzz",5)'nota citando per la shell e trailing virgola per un ingresso.

  • Risolto errore di 1am cambiando da dict (ordinamento indefinito!) A tuple.

  • L'input previsto per gli altri programmi è solo il numero


Nel tuo esempio di riga di comando, ho dovuto racchiudere virgolette doppie e usare virgolette singole per 'Fizz' e 'Buzz' - in questo modo `" {3: 'Fizz', 5: 'Buzz'} ", tuttavia il programma è ancora lanciare un errore per me.
James Williams,

Qual è l'errore?
Jason S

@JasonS - Ciao a tutti. Sono interessato alla tua esperienza di questa sfida. meta.codegolf.stackexchange.com/questions/5050/…
billpg

6

perl6 376 340 84 + 115 = 199

AGGIORNAMENTO: passato da perl5 a perl6 per ottenere saysenza use feature.

AGGIORNAMENTO: tre casi di test anziché cinque

Esistono centinaia di soluzioni già giocate a FizzBuzz e molti contest terminano con lo stesso risultato, quindi è da lì che ho iniziato. Il mio compilatore produce solo una versione personalizzata di quella soluzione. Sono stati inseriti alcuni caratteri extra per tenere conto della variazione "just count".

compilatore, si aspetta argomenti del genere: "Fizz 3" "Buzz 5"

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

programmi compilati, aspettatevi argomenti come questi: 100

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

programmi compilati per vecchi casi di test:

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

Ho cambiato le regole come discusso nei commenti della domanda. Ti consigliamo di ricalcolare il tuo punteggio.
billpg,

@billpg fatto e migliorato :)
Sparr

Ciao. Sono interessato alla tua esperienza di questa sfida. meta.codegolf.stackexchange.com/questions/5050/…
billpg

3

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

Probabilmente può golf il compilatore di pochi byte. I collegamenti su tutti loro sono permalink all'interprete online.

Compilatore - 51 byte

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

Fa solo la formattazione delle stringhe con una tupla di input. Accetta input come:

3 5
Fizz Buzz

Niente : 38 byte

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

Solo golf - 43 byte

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

Fizz Buzz classico - 50 byte

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

2

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

Prima partecipazione qui, questa sfida non è tra le più difficili, quindi ho pensato di provarlo. Utilizzando C ++ però, e anche con le aggiunte C ++ 11 è ancora un linguaggio piuttosto prolisso, ma sono sicuro che c'è spazio per miglioramenti.

Compilatore (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;}

Presuppone argomenti sotto forma di 3Fizz 5Buzzecc.

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

Informazioni aggiuntive

Testato con GCC 4.8.1, nessun trucco del compilatore.

Ecco un piccolo makefile per automatizzare la generazione dei casi di test ed eseguirli (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

Ciao. Sono interessato alla tua esperienza di questa sfida. meta.codegolf.stackexchange.com/questions/5050/…
billpg

map<int,string> fpotrebbe essere map<int,string>f. È possibile inizializzare j=1allo stesso tempo con z.
Yytsi,

2

Rubino 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

Esegui ed esegui il debug

La risposta più breve finora Non sorprendentemente battuto da Jelly. Il modello di stringa fornito in Stax è davvero pulito e offre funzioni simili a printf. I programmi generati dal compilatore sono quasi sempre brevi quanto i migliori che si possono ottenere codegolfando manualmente, senza usare il packaging.

Il compilatore stesso ha una lunghezza di 23 byte .

L'equivalente ASCII è:

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

Fornito input [], genera questo (5 byte)

mzc_?

Esegui ed esegui il debug

Fornito input [[1,"Golf"]], genera questo (17 byte)

mz_1%z"Golf"?+c_?

Esegui ed esegui il debug

Fornito input [[3,"Fizz"],[5,"Buzz"]], genera questo (29 byte)

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

Esegui ed esegui il debug


1

Lisp comune, 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)))

Ho preso la mia altra risposta e l'ho racchiusa in quasiquote aggiungendo parametri di input. Stampo il modulo risultante come una riga singola e rimuovo i caratteri inutili degli spazi bianchi. Il compilatore è un po 'più lungo della versione precedente, ma il punteggio risultante è ridotto.

Punto

(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))))

Valori restituiti:

574
(215 111 119 129)

Bella

(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)))

Il formato di input è un elenco di (number string)coppie. Per esempio:

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

... stampa sullo standard output:

(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)))))

... che, piuttosto stampato, è:

(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)))))

Test della funzione risultante:

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 byte totali

Compilatore [369 byte]

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

Fizz Buzz [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);}

Conteggio [233 byte]

#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

dc , 434 byte

[: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

Provalo online!

L'input per il compilatore (168 byte) deve essere inserito nello stack come intero, stringa, intero, stringa e così via ( 3 [Fizz] 5 [Buzz]). Dovrebbe essere dato nell'ordine in cui si desidera stampare le loro fizzes e ronzii, il che potrebbe essere un po 'un imbroglione (avendo implementato l'ordinamento delle bolle in dcprecedenza, credo che mi costerebbe circa 100 byte) ma consente anche all'utente di , diciamo, avere ancora "Fizz" su 3 e "Buzz" su 5, ma con 15 "BuzzFizz".

Sono sicuro che questo può essere giocato un po 'di più; la macro principale nel programma finale ( M) si basa su due macro ( Fe P) che sono piuttosto inutili dato nessun input. In questo momento il compilatore controlla input e output versioni diverse (molto più piccole) di queste macro se non ce ne sono, ma non sono sicuro che l'intero setup sia ottimale.

Il compilatore stesso è piuttosto semplice, controlla solo se ci sono "regole" nello stack e, in tal caso, stampa il codice che memorizza la profondità dello stack in z , memorizza lo stack in un array con indice 0 ae quindi stampa il generalizzato Codice FizzBuzz. Se non c'era nulla nello stack, in realtà stampa solo una versione modificata del codice FizzBuzz. Casi test:

Nessun input (46 byte):

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

3 [Fizz] 5 [Buzz] (117 byte):

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 byte):

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

Si aspettano tutti il valore n nello stack, questo viene archiviato n. Quelli che hanno "regole" li posizionano nella matrice a, con le stringhe agli indici dispari e gli interi ai pari. La macro principale M, incrementa tutto ciò che è nello stack, esegue la macro Fche controlla il valore rispetto all'array a, verifica se Fimposta register bsu true o no e stampa la parte superiore dello stack in tal caso o una nuova riga in caso contrario, ripristinab falsità e quindi mantiene si esegue se nnon è stato ancora raggiunto. La macro F, date le regole, passa attraverso l'intero array in cerca di corrispondenze. Aumenta di due poiché i nostri numeri interi e stringhe sono intrecciati attraverso l'array e su una corrispondenza chiama macroB . macroBrecupera semplicemente la stringa (posizione corrente nell'array meno una) e la stampa. Imposta anche bsu verità. Il nostro compilatore non si preoccupa di stampare Bsenza input, e sostanzialmente fa Fun nop.


0

vim, 122 (compilatore) + 73 (vuoto) + 90 (golf) + 123 (fizzbuzz) = 392 byte

Compiler

:%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 di input

3:Fizz
5:Buzz

Codice generato per il 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! %

Codice generato, annotato

# 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> è 0x16. <ESC>è 0x1b. <C-A>è 0x01.

Sessione di esempio

$ 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

C'è qualcosa di strano che succede quando provo a definire ed eseguire una macro da un'altra macro. Se riesco a risolverlo, potrei salvare qualche byte sull'approccio di salvataggio e di origine.
Ray

-2

SlooSarksi .Lang, 179

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

10
Non ho familiarità con questa lingua; potresti collegarci a una pagina che lo descrive?
lirtosiast,
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.