Crie um compilador FizzBuzz


17

Bem-vindo ao mundo do golfe de compiladores. Sua tarefa é escrever um programa que gere outro programa para reproduzir uma variante do FizzBuzz na especificação.

Seu compilador

Escreva um compilador que gere variantes do programa FizzBuzz para especificar. A especificação desta variante é expressa na forma de uma matriz de pares de número inteiro / sequência.

  • A entrada pode estar em qualquer forma que seja conveniente para o seu idioma. (Meus exemplos usam n: xxxx, mas isso é apenas para fins ilustrativos.)
  • Cada entrada inteira pode ser usada apenas uma vez por chamada do seu compilador.
  • O número inteiro de cada par terá um valor de pelo menos um.
  • A sequência de cada par será composta apenas de exatamente quatro letras ASCII.
  • A saída deve ser um único programa completo que esteja em conformidade com as regras abaixo.
  • A saída pode estar em qualquer forma conveniente, desde que seja um programa textual. (Portanto, não retorne expressões lambda.)

O comportamento é indefinido para entradas que não estão em conformidade com as regras acima.

Seu programa FizzBuzz gerado

O programa gerado pelo seu compilador terá um único número inteiro, n , como entrada. Ele produzirá uma sequência de números começando de um até e incluindo n , substituindo números por sequências de caracteres do FizzBuzz, quando necessário.

  • O programa gerado deve estar no mesmo idioma que o compilador.
  • A entrada n pode estar de qualquer forma conveniente para o seu idioma.
  • n terá um valor de pelo menos um.
  • Um número que é múltiplo de pelo menos um dos números inteiros de entrada no compilador deve ser substituído por todas as seqüências de caracteres emparelhadas com os números inteiros unidos.
  • Um número que não deve ser substituído por uma string do FizzBuzz deve ser emitido em ASCII decimal.

Por exemplo;

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

Pontuação

Sua entrada será pontuada pela duração dos programas que o seu compilador gera adicionados à duração do seu compilador. Execute seu compilador várias vezes com cada um dos seguintes parâmetros e adicione os comprimentos dos programas gerados juntamente com o comprimento do compilador para encontrar sua pontuação.

  1. Apenas conte. (Nenhuma entrada - o programa gerado contará de 1 a n sem substituições.)
  2. Apenas golfe. (1: Golf - O programa gerado produzirá "Golf" n vezes.)
  3. FizzBuzz clássico. (3: Fizz, 5: Buzz)

(Observe que seu compilador é necessário para gerar código para qualquer entrada válida, não apenas as listadas.)


sem pontuação para o comprimento do compilador ??
Sparr 31/07

podemos assumir que os números inteiros são de um dígito? que não há espaços nas cordas?
Sparr

@Sparr Isso (números inteiros de dois dígitos) faria diferença? Lembre-se, é apenas o código gerado que faz sua pontuação.
billpg

bem, o fizzbuzz é um problema já extremamente bem praticado em outras partes da internet. Não sei se poderia esquecer de ler a solução, se tentasse.
Sparr 31/07

11
Finalmente, um desafio de golfe que realmente faz sentido escrever em AWK.
Shadowtalker

Respostas:


8

Python 3 - 168 162 + 230 = 392

Oh, Python, você se esforça tanto, mas multiplicar import sys;sys.argvpor 4 realmente dói!

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 saída:

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))
  • A entrada esperada para o programa principal é uma sequência evalable de tuplas Python ou '()'para nenhuma entrada. (Você disse "conveniente".) De entrada Exemplo: '()', '("Golf",1),', '("Fizz",3),("Buzz",5)'Nota citando para shell e vírgula à direita para uma entrada.

  • Corrigido o erro de 1h, mudando de dict (pedido indefinido!) Para tuplas.

  • A entrada esperada para os outros programas é apenas o número


No seu exemplo de argumento de linha de comando, eu tive que colocar aspas duplas e usar aspas simples para 'Fizz' e 'Buzz' - como assim "" {3: 'Fizz', 5: 'Buzz'} ", mas o programa ainda está jogando um erro para mim.
James Williams

Qual é o erro?
Jason S #

@ Jason - Olá. Estou interessado na sua experiência com este desafio. meta.codegolf.stackexchange.com/questions/5050/…
billpg 9/15

6

perl6 376 340 84 + 115 = 199

UPDATE: mudou de perl5 para perl6 para ficar saysem use feature.

UPDATE: três casos de teste em vez de cinco

Existem centenas de soluções já disputadas para o FizzBuzz, e muitos concursos terminam com o mesmo resultado, então foi aí que comecei. Meu compilador apenas produz uma versão personalizada dessa solução. Alguns caracteres extras foram inseridos para explicar a variação "apenas contar".

compilador, espera argumentos assim: "Fizz 3" "Buzz 5"

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

programas compilados, espere argumentos assim: 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 teste antigos:

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

Alterei as regras conforme discutido nos comentários da pergunta. Você deseja recalcular sua pontuação.
billpg

@billpg feito, e melhorou :)
Sparr

Olá. Estou interessado na sua experiência com este desafio. meta.codegolf.stackexchange.com/questions/5050/…
billpg 9/15

3

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

Provavelmente pode jogar golfe no compilador alguns bytes. Os links de todos eles são permalinks para o intérprete online.

Compilador - 51 bytes

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

Apenas faz a formatação de strings com uma tupla de entrada. Aceita entradas 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

Buzz clássico do Fizz - 50 bytes

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

2

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

Primeira participação aqui, esse desafio não está entre os mais difíceis, então pensei em tentar. No entanto, usando C ++, e mesmo com adições ao C ++ 11, ainda é uma linguagem bastante detalhada, mas tenho certeza de que há espaço para melhorias.

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

Ele assume argumentos na forma de 3Fizz 5Buzzetc.

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

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

Informação adicional

Testado com o GCC 4.8.1, sem truques do compilador.

Aqui está um pequeno makefile para automatizar a geração dos casos de teste e executá-los (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

Olá. Estou interessado na sua experiência com este desafio. meta.codegolf.stackexchange.com/questions/5050/…
billpg 9/15

map<int,string> fpoderia ser map<int,string>f. Você pode inicializar j=1ao mesmo tempo com z.
Yytsi 24/09/16

2

Ruby 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

Execute e depure

Resposta mais curta até agora Não surpreendentemente derrotado por Jelly. O modelo de string fornecido no Stax é realmente elegante e fornece funções do tipo printf. Os programas gerados pelo compilador são quase sempre tão curtos quanto os melhores, codegolfing manualmente, sem usar empacotamento.

O compilador em si tem 23 bytes .

O equivalente ASCII é:

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

Entrada fornecida [], gera esta (5 bytes)

mzc_?

Execute e depure

Entrada fornecida [[1,"Golf"]], gera esta (17 bytes)

mz_1%z"Golf"?+c_?

Execute e depure

Entrada fornecida [[3,"Fizz"],[5,"Buzz"]], gera esta (29 bytes)

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

Execute e depure


1

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

Peguei minha outra resposta e envolvi-a em quasiquotes enquanto adicionava parâmetros de entrada. Imprimo o formulário resultante como uma linha única e removo caracteres desnecessários de espaço em branco. O compilador é um pouco mais longo que a versão anterior, mas a pontuação resultante é reduzida.

Ponto

(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 retornados:

574
(215 111 119 129)

Bonita

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

O formato de entrada é uma lista de (number string)casais. Por exemplo:

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

... imprime na saída padrão:

(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, bem impresso, é:

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

Testando a função 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, total de 1080 bytes

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

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

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

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

dc , 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

Experimente online!

A entrada para o compilador (168 bytes) deve ser colocada na pilha como número inteiro, sequência, número inteiro, sequência e assim por diante (3 [Fizz] 5 [Buzz] ). Deveria ser dada na ordem em que se deseja que seus efervescentes e zumbidos sejam impressos, o que pode ser um truque (tendo implementado o tipo de bolha emdc antes, acredito que custaria cerca de 100 bytes), mas também permite ao usuário , digamos, ainda tenha 'Fizz' executado em 3 e 'Buzz' em 5, mas tenha 15 rendimentos 'BuzzFizz'.

Tenho certeza de que isso pode ser jogado um pouco mais; a macro principal no programa final ( M) depende de duas macros (F eP ) que são bastante desnecessárias, dado que não há informações. No momento, o compilador verifica as entradas e saídas de versões diferentes (muito menores) dessas macros, se não houver nenhuma, mas não tenho certeza de que toda a instalação seja ótima.

O compilador em si é bastante direto, apenas verifica se há 'regras' na pilha e, se for o caso, imprime o código que armazena a profundidade da pilha z, armazena a pilha em uma matriz indexada em 0 ae depois imprime o generalizado Código FizzBuzz. Se não havia nada na pilha, ele realmente imprime apenas uma versão modificada do código do FizzBuzz. Casos de teste:

Nenhuma entrada (46 bytes):

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

3 [Fizz] 5 [Buzz] (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 [Golfe] (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 esperam que o valor n na pilha seja armazenado n. Os que possuem 'regras' os colocam na matriz a, com as seqüências de caracteres em índices ímpares e os números inteiros em pares. A macro principal,M , incrementa o que estiver na pilha, executa a macro Fque verifica o valor em relação à matriz a, verifica se o Fregistro é definido bcomo verdadeiro ou não e imprime o topo da pilha, se houver, ou uma nova linha, se não, redefine bpara falsidade e depois mantém executando-se sen ainda não foi alcançado. A macro F, dadas regras, percorre toda a matriz em busca de correspondências. Ele é incrementado em dois, uma vez que nossos números inteiros e seqüências de caracteres são tecidos através da matriz e, em uma correspondência, chama macro B. MacroBapenas recupera a string (posição atual na matriz menos uma) e a imprime. Também define bcomo verdade. Nosso compilador não se preocupa em imprimir Bsem entrada e essencialmente faz Fum nop.


0

vim, 122 (compilador) + 73 (vazio) + 90 (golfe) + 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 gerado para o 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 gerado, 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>é 0x16. <ESC>é 0x1b. <C-A>é 0x01.

Sessão de exemplo

$ 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

Há algo estranho acontecendo quando tento definir e executar uma macro de dentro de outra macro. Se eu conseguir resolver isso, posso salvar alguns bytes sobre a abordagem de salvar e de origem.
Raio

-2

SlooSarksi .Lang, 179

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

10
Eu não estou familiarizado com esse idioma; você poderia nos vincular a uma página que a descreve?
lirtosiast
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.