Créer un compilateur FizzBuzz


17

Bienvenue dans le monde du golf de compilation. Votre tâche consiste à écrire un programme qui génère un autre programme pour lire une variante de FizzBuzz sur spec.

Votre compilateur

Écrivez un compilateur qui génère des variantes du programme FizzBuzz à spec. La spécification de cette variante est exprimée sous la forme d'un tableau de paires entiers / chaînes.

  • L'entrée peut être sous n'importe quelle forme qui convient à votre langue. (Mes exemples utilisent n: xxxx, mais ce n'est qu'à des fins d'illustration.)
  • Chaque entrée entière ne peut être utilisée qu'une seule fois par appel de votre compilateur.
  • L'entier de chaque paire aura une valeur d'au moins un.
  • La chaîne de chaque paire sera composée uniquement de quatre lettres ASCII.
  • La sortie doit être un seul programme complet conforme aux règles ci-dessous.
  • La sortie peut être sous n'importe quelle forme pratique, tant qu'il s'agit d'un programme textuel. (Donc pas d'expressions lambda retournées.)

Le comportement n'est pas défini pour les entrées non conformes aux règles ci-dessus.

Votre programme FizzBuzz généré

Le programme généré par votre compilateur prendra un seul entier, n , en entrée. Il produira une séquence de nombres allant de un à n inclus , en remplaçant les nombres par des chaînes FizzBuzz si nécessaire.

  • Le programme généré doit être dans la même langue que le compilateur.
  • L'entrée n peut être sous n'importe quelle forme adaptée à votre langue.
  • n aura une valeur d'au moins un.
  • Un nombre qui est un multiple d'au moins l'un des entiers entrés dans le compilateur doit être remplacé par toutes les chaînes associées à ces entiers réunis.
  • Un nombre qui ne doit pas être remplacé par une chaîne FizzBuzz doit être sorti en ASCII décimal.

Par exemple;

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

Notation

Votre entrée sera notée par la longueur des programmes générés par votre compilateur ajoutée à la longueur de votre compilateur. Exécutez votre compilateur plusieurs fois avec chacun des paramètres suivants et ajoutez les longueurs des programmes générés ainsi que la longueur du compilateur pour trouver votre score.

  1. Il suffit de compter. (Aucune entrée - Le programme généré comptera de 1 à n sans remplacements.)
  2. Just Golf. (1: Golf - Le programme généré affichera "Golf" n fois.)
  3. FizzBuzz classique. (3: Fizz, 5: Buzz)

(Notez que votre compilateur est requis pour générer du code pour toute entrée valide, pas seulement celles listées.)


pas de score pour la longueur du compilateur ??
Sparr le

pouvons-nous supposer que les entiers sont à un seul chiffre? qu'il n'y a pas d'espaces dans les cordes?
Sparr

@Sparr Cela (des nombres à deux chiffres) ferait-il une différence? Rappelez-vous, ce n'est que le code généré qui fait votre score.
billpg

eh bien, le fizzbuzz est un problème déjà extrêmement approfondi ailleurs sur Internet. Je ne sais pas si je pourrais oublier de lire la solution si j'essayais.
Sparr

1
Enfin un défi de golf qui a du sens d'écrire en AWK.
shadowtalker

Réponses:


8

Python 3 - 168 162 + 230 = 392

Oh, Python, tu essayes si fort, mais multiplier le import sys;sys.argvcontenu par 4 fait vraiment mal!

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

Programmes de sortie:

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'entrée attendue pour le programme principal est une séquence évaluable de tuples Python ou '()'pour aucune entrée. (Vous avez dit « pratique ».) Exemple d' entrée: '()', '("Golf",1),', '("Fizz",3),("Buzz",5)'note citant shell et virgule de fin pour une entrée.

  • Correction d'une erreur à 1 heure du matin en passant de dict (ordre non défini!) À tuples.

  • L'entrée attendue pour les autres programmes n'est que le nombre


Dans votre exemple d'argument de ligne de commande, j'ai dû mettre des guillemets doubles et utiliser des guillemets simples pour 'Fizz' et 'Buzz' - comme si "" {3: 'Fizz', 5: 'Buzz'} "mais le programme est toujours jetant une erreur pour moi.
James Williams

Quelle est l'erreur?
Jason S

@JasonS - Salut. Je suis intéressé par votre expérience de ce défi. meta.codegolf.stackexchange.com/questions/5050/…
billpg

6

perl6 376 340 84 + 115 = 199

MISE À JOUR: passé de perl5 à perl6 pour s'en saypasser use feature.

MISE À JOUR: trois cas de test au lieu de cinq

Il existe des centaines de solutions déjà utilisées pour FizzBuzz, et de nombreux concours se terminent avec le même résultat, c'est donc là que j'ai commencé. Mon compilateur produit juste une version personnalisée de cette solution. Quelques caractères supplémentaires ont été insérés pour tenir compte de la variation "juste compter".

compilateur, attend des arguments comme ceci: "Fizz 3" "Buzz 5"

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

programmes compilés, attendez-vous à un argument comme celui-ci: 100

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

programmes compilés pour les anciens cas de 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]

J'ai changé les règles comme discuté dans les commentaires de la question. Vous voudrez recalculer votre score.
billpg

@billpg terminé et amélioré :)
Sparr

Salut. Je suis intéressé par votre expérience de ce défi. meta.codegolf.stackexchange.com/questions/5050/…
billpg

3

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

Peut probablement jouer au compilateur quelques octets. Les liens sur chacun d'eux sont des liens permanents vers l'interprète en ligne.

Compilateur - 51 octets

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

Effectue simplement le formatage des chaînes avec un tuple d'entrée. Prend des informations comme:

3 5
Fizz Buzz

Rien - 38 octets

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

Just Golf - 43 octets

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

Fizz Buzz classique - 50 octets

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

2

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

Première participation ici, ce défi n'est pas parmi les plus difficiles donc j'ai pensé que je devrais l'essayer. Cependant, en utilisant C ++, et même avec des ajouts C ++ 11, c'est toujours un langage assez verbeux, mais je suis sûr qu'il y a place à amélioration.

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

Il suppose des arguments sous la forme de 3Fizz 5Buzzetc.

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

Information additionnelle

Testé avec GCC 4.8.1, aucun compilateur ne triche.

Voici un petit makefile pour automatiser la génération des cas de test et les exécuter (utilisation 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

Salut. Je suis intéressé par votre expérience de ce défi. meta.codegolf.stackexchange.com/questions/5050/…
billpg

map<int,string> fpourrait être map<int,string>f. Vous pouvez initialiser j=1en même temps avec z.
Yytsi

2

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

Usage:

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

Exécuter et déboguer

Réponse la plus courte à ce jour Sans surprise battue par Jelly. Le modèle de chaîne fourni dans Stax est vraiment soigné et fournit des fonctions de type printf. Les programmes générés par le compilateur sont presque toujours aussi courts que les meilleurs peuvent être obtenus en jouant au code manuellement, sans utiliser d'emballage.

Le compilateur lui-même fait 23 octets de long.

L'équivalent ASCII est:

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

Entrée fournie [], génère celle-ci (5 octets)

mzc_?

Exécuter et déboguer

Entrée fournie [[1,"Golf"]], génère celle-ci (17 octets)

mz_1%z"Golf"?+c_?

Exécuter et déboguer

Entrée fournie [[3,"Fizz"],[5,"Buzz"]], génère celle-ci (29 octets)

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

Exécuter et déboguer


1

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

J'ai pris mon autre réponse et l' ai enveloppée dans des quasiquotes tout en ajoutant des paramètres d'entrée. J'imprime le formulaire résultant en une seule ligne et supprime les caractères blancs inutiles. Le compilateur est un peu plus long que la version précédente, mais le score résultant est réduit.

But

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

Valeurs renvoyées:

574
(215 111 119 129)

Jolie

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

Le format d'entrée est une liste de (number string)couples. Par exemple:

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

... imprime sur la sortie standard:

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

... ce qui, joliment imprimé, c'est:

(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 de la fonction résultante:

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 octets au total

Compilateur [369 octets]

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

Nombre [233 octets]

#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 octets

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

Essayez-le en ligne!

L'entrée du compilateur (168 octets) doit être placée sur la pile sous forme d'entier, de chaîne, d'entier, de chaîne, etc. (3 [Fizz] 5 [Buzz] ). Il doit être donné dans l'ordre où l'on veut que leurs pétillements et bourdonnements soient imprimés, ce qui peut être un peu une triche (après avoir implémenté le tri à bulles dcauparavant, je pense que cela me coûterait environ 100 octets), mais cela permet également à l'utilisateur de , disons, ont toujours «Fizz» exécuté sur 3 et «Buzz» exécuté sur 5, mais ont 15 rendement «BuzzFizz».

Je suis sûr que cela peut être joué un peu plus; la macro principale du programme final (M ) repose sur deux macros ( FetP ) qui sont plutôt inutiles étant donné aucune entrée. En ce moment, le compilateur vérifie les entrées et sorties de différentes versions (beaucoup plus petites) de ces macros s'il n'y en a pas, mais je ne suis pas sûr que la configuration entière soit optimale.

Le compilateur lui-même est assez simple, il vérifie simplement s'il y a des «règles» sur la pile, et si c'est le cas, il imprime du code qui stocke la profondeur de la pile dans z, stocke la pile dans un tableau indexé 0a , puis imprime le généralisé Code FizzBuzz. S'il n'y avait rien sur la pile, il imprime simplement une version modifiée du code FizzBuzz. Cas de test:

Aucune entrée (46 octets):

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

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

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

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

Ils attendent tous la valeur n sur la pile, celle-ci est stockée n. Ceux qui ont des «règles» les placent dans le tableau a, avec les chaînes aux indices impairs et les entiers à evens. La macro principale M, incrémente tout ce qui se trouve sur la pile, exécute une macro Fqui vérifie la valeur par rapport au tableau a, vérifie si le Fregistre est défini bsur true ou non et imprime le haut de la pile dans l'affirmative ou une nouvelle ligne dans le cas contraire, se réinitialise bsur falsy, puis conserve s'exécutant si nn'a pas encore été atteint. La macro récupère simplement la chaîne (position actuelle dans le tableau moins un) et l'imprime. Il se met également à la vérité. Notre compilateur ne prend pas la peine d'imprimer sans aucune entrée, et fait essentiellementF , compte tenu des règles, parcourt tout le tableau à la recherche de correspondances. Il incrémente de deux puisque nos entiers et chaînes sont tissés à travers le tableau, et sur une correspondance il appelle macro B. MacroBbBF un nop.


0

vim, 122 (compilateur) + 73 (vide) + 90 (golf) + 123 (fizzbuzz) = 392 octets

Compilateur

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

Format d'entrée

3:Fizz
5:Buzz

Code généré pour le boîtier 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! %

Code généré, annoté

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

Exemple de session

$ 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

Il se passe quelque chose d'étrange lorsque j'essaie de définir et d'exécuter une macro à partir d'une autre macro. Si je parviens à trier cela, je pourrais économiser quelques octets sur l'approche de sauvegarde et de source.
Ray

-2

SlooSarksi .Lang, 179

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

10
Je ne connais pas cette langue; pourriez-vous nous lier à une page le décrivant?
lirtosiast
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.