Utwórz kompilator FizzBuzz


17

Witamy w świecie kompilatora golfa. Twoim zadaniem jest napisanie programu, który generuje inny program do odtwarzania określonego wariantu FizzBuzz.

Twój kompilator

Napisz kompilator, który generuje warianty programu FizzBuzz do specyfikacji. Specyfikacja tego wariantu jest wyrażona w postaci tablicy liczb całkowitych / ciągów znaków.

  • Dane wejściowe mogą mieć dowolną formę dogodną dla twojego języka. (Moje przykłady używają n: xxxx, ale jest to wyłącznie w celach ilustracyjnych.)
  • Każde wejście całkowite może być użyte tylko raz na wywołanie twojego kompilatora.
  • Liczba całkowita każdej pary będzie miała wartość co najmniej jednej.
  • Ciąg każdej pary będzie składał się tylko z dokładnie czterech liter ASCII.
  • Dane wyjściowe muszą być pojedynczym kompletnym programem, który jest zgodny z poniższymi zasadami.
  • Wynik może być w dowolnej dogodnej formie, o ile jest to program tekstowy. (Więc nie ma wyrażeń lambda.)

Zachowanie jest niezdefiniowane dla danych wejściowych niezgodnych z powyższymi zasadami.

Wygenerowany program FizzBuzz

Program wygenerowany przez kompilator pobierze jedną liczbę całkowitą n jako dane wejściowe. Wyświetli sekwencję liczb od jednego do n włącznie , w razie potrzeby zamieniając liczby ciągami FizzBuzz.

  • Wygenerowany program musi być w tym samym języku co kompilator.
  • Wpis n może mieć dowolną formę dogodną dla twojego języka.
  • n będzie miało wartość co najmniej jednego.
  • Liczba będąca wielokrotnością co najmniej jednej liczby całkowitej wprowadzonej do kompilatora musi zostać zastąpiona przez wszystkie ciągi sparowane z tymi liczbami całkowitymi połączonymi ze sobą.
  • Liczba, która nie ma być zastępowana ciągiem FizzBuzz, musi być wyprowadzana w postaci dziesiętnej ASCII.

Na przykład;

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

Punktacja

Twój wpis będzie oceniany na podstawie długości programów generowanych przez kompilator dodanych do długości twojego kompilatora. Uruchom kompilator wiele razy z każdym z poniższych parametrów i dodaj długości wygenerowanych programów wraz z długością kompilatora, aby znaleźć swój wynik.

  1. Po prostu policz. (Brak danych wejściowych - wygenerowany program będzie liczyć od 1 do n bez zamiany).
  2. Po prostu golf. (1: Golf - wygenerowany program wyświetli „Golf” n razy.)
  3. Klasyczny FizzBuzz. (3: Fizz, 5: Buzz)

(Pamiętaj, że Twój kompilator jest wymagany do generowania kodu dla dowolnego prawidłowego wejścia, nie tylko tych wymienionych).


brak punktacji za długość kompilatora?
Sparr

czy możemy założyć, że liczby całkowite są jednocyfrowe? że w ciągach znaków nie ma spacji?
Sparr

@Sparr Czy to (dwucyfrowe liczby całkowite) miałyby znaczenie? Pamiętaj, że tylko wygenerowany kod sprawia, że ​​twój wynik.
billpg

cóż, fizzbuzz to już bardzo dokładnie gra w golfa w innych miejscach w Internecie. Nie wiem, czy mógłbym zapomnieć o przeczytaniu rozwiązania, gdybym spróbował.
Sparr

1
Wreszcie wyzwanie golfowe, które w rzeczywistości ma sens pisać w AWK.
shadowtalker

Odpowiedzi:


8

Python 3 - 168 162 + 230 = 392

Och, Python, bardzo się starasz, ale pomnożenie tego import sys;sys.argvprzez 4 naprawdę boli!

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

Programy wyjściowe:

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))
  • Oczekiwanym wejściem dla programu głównego jest możliwa do sprawdzenia sekwencja krotek Pythona lub '()'brak danych wejściowych. (Można było powiedzieć „wygodny”). Przykład Wejście: '()', '("Golf",1),', '("Fizz",3),("Buzz",5)'Uwaga cytowanie na skorupkach i na końcu przecinek do jednego wejścia.

  • Naprawiono błąd 1 rano, zmieniając z dict (niezdefiniowane porządkowanie!) Na krotki.

  • Oczekiwanym wejściem dla innych programów jest tylko liczba


W przykładowym argumencie wiersza poleceń musiałem zawijać podwójne cudzysłowy i używać pojedynczych cudzysłowów dla „Fizz” i „Buzz” - tak jak „„ {3: „Fizz”, 5: „Buzz”} ”, jednak program jest nadal rzucając mi błąd.
James Williams

Jaki jest błąd?
Jason S

@JasonS - Cześć. Jestem zainteresowany twoimi doświadczeniami związanymi z tym wyzwaniem. meta.codegolf.stackexchange.com/questions/5050/…
billpg

6

perl6 376 340 84 + 115 = 199

AKTUALIZACJA: zmieniono z perl5 na perl6, aby się saybez niego obejść use feature.

AKTUALIZACJA: trzy przypadki testowe zamiast pięciu

Istnieją setki już rozwiązanych rozwiązań FizzBuzz, a wiele konkursów kończy się z takim samym rezultatem, więc od tego zacząłem. Mój kompilator tworzy właśnie dostosowaną wersję tego rozwiązania. Dodano kilka dodatkowych znaków, aby uwzględnić odmianę „wystarczy policzyć”.

kompilator, oczekuje takich argumentów: „Fizz 3” „Buzz 5”

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

skompilowane programy, spodziewaj się takiego argumentu: 100

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

skompilowane programy dla starych przypadków testowych:

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

Zmieniłem zasady zgodnie z opisem w komentarzach do pytania. Będziesz chciał ponownie obliczyć swój wynik.
billpg

@billpg zrobione i poprawione :)
Sparr

Cześć. Jestem zainteresowany twoimi doświadczeniami związanymi z tym wyzwaniem. meta.codegolf.stackexchange.com/questions/5050/…
billpg

3

Pyth - 51 + (38 + 43 + 50) = 182 bajtów

Potrafi prawdopodobnie zagrać w kompilator kilka bajtów. Wszystkie linki są linkami do tłumacza online.

Kompilator - 51 bajtów

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

Po prostu formatuje ciąg za pomocą krotki wejściowej. Pobiera dane wejściowe takie jak:

3 5
Fizz Buzz

Nic - 38 bajtów

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

Just Golf - 43 bajty

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

Klasyczny Fizz Buzz - 50 bajtów

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

2

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

Pierwsze uczestnictwo tutaj, to wyzwanie nie należy do najtrudniejszych, więc pomyślałem, że spróbuję. Korzystając z C ++, a nawet z dodatkami do C ++ 11, jest to wciąż dość pełny język, ale jestem pewien, że jest miejsce na ulepszenia.

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

Zakłada argumenty w postaci 3Fizz 5Buzzitp.

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

Dodatkowe informacje

Testowane z GCC 4.8.1, bez kodów kompilatora.

Oto mały plik makefile do automatyzacji generowania przypadków testowych i uruchamiania ich (użyj 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

Cześć. Jestem zainteresowany twoimi doświadczeniami związanymi z tym wyzwaniem. meta.codegolf.stackexchange.com/questions/5050/…
billpg

map<int,string> fmoże być map<int,string>f. Możesz zainicjować j=1w tym samym czasie za pomocą z.
Yytsi

2

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

Stosowanie:

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

Uruchom i debuguj

Najkrótsza jak dotąd odpowiedź Nie zaskakująco pobita przez Galaretkę. Szablon napisów w Staxie jest naprawdę schludny i zapewnia funkcje podobne do printf. Programy generowane przez kompilator są prawie zawsze tak krótkie, jak najlepsze, jakie można osiągnąć, ręcznie kodując kodowanie bez użycia pakowania.

Sam kompilator ma 23 bajty .

Odpowiednikiem ASCII jest:

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

Podane dane wejściowe []generują ten (5 bajtów)

mzc_?

Uruchom i debuguj

Podane dane wejściowe [[1,"Golf"]]generują ten (17 bajtów)

mz_1%z"Golf"?+c_?

Uruchom i debuguj

Podane dane wejściowe [[3,"Fizz"],[5,"Buzz"]]generują ten (29 bajtów)

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

Uruchom i debuguj


1

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

Wziąłem inną odpowiedź i zawinąłem ją w quasi-cytaty, dodając parametry wejściowe. Powstały formularz drukuję jako jednowierszowy i usuwam niepotrzebne białe znaki. Kompilator jest nieco dłuższy niż poprzednia wersja, ale wynik jest mniejszy.

Wynik

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

Zwrócone wartości:

574
(215 111 119 129)

Ładny

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

Format wejściowy to lista (number string)par. Na przykład:

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

... drukuje na standardowe wyjście:

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

... która, ładnie wydrukowana, jest:

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

Testowanie wynikowej funkcji:

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, łącznie 1080 bajtów

Kompilator [369 bajtów]

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

Policz [233 bajty]

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

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

Wypróbuj online!

Dane wejściowe kompilatora (168 bajtów) należy umieścić na stosie jako liczbę całkowitą, ciąg, liczbę całkowitą, ciąg itd. ( 3 [Fizz] 5 [Buzz]). Powinien być podany w takiej kolejności, w jakiej chce się wydrukować jego szumy i szumy, co może być trochę oszustwem (po wdrożeniu sortowania bąbelkowego dcwcześniej, sądzę, że kosztowałoby mnie to około 100 bajtów), ale pozwala również użytkownikowi , powiedzmy, nadal „Fizz” działa na 3 i „Buzz” na 5, ale mają 15 wydajności „BuzzFizz”.

Jestem pewien, że można to trochę pograć w golfa; główne makro w programie końcowym (M ) opiera się na dwóch makrach ( FiP ), które są raczej niepotrzebne, jeśli nie zostaną wprowadzone. W tej chwili kompilator sprawdza wejścia i wyjścia różnych (znacznie mniejszych) wersji tych makr, jeśli ich nie ma, ale nie jestem pewien, czy cała konfiguracja jest optymalna.

Sam kompilator jest dość prosty, po prostu sprawdza, czy na stosie znajdują się „reguły”, a jeśli tak, to drukuje kod, który przechowuje głębokość stosu z , przechowuje stos w tablicy o indeksie 0 a, a następnie drukuje uogólniony Kod FizzBuzz. Jeśli na stosie nie było nic, to po prostu drukuje zmodyfikowaną wersję kodu FizzBuzz. Przypadki testowe:

Brak danych wejściowych (46 bajtów):

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

3 [Fizz] 5 [Buzz] (117 bajtów):

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

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

Wszyscy oczekują wartości n na stosie, która zostaje zapisana n. Te, które mają „reguły”, umieszczają je w tablicy a, przy czym ciągi znaków mają nieparzyste wskaźniki, a liczby całkowite są równe. Główne makro, Minkrementuje wszystko, co znajduje się na stosie, uruchamia makro, Fktóre sprawdza wartość względem tablicy a, sprawdza, czy Fustawiono rejestr bna wartość true, czy nie, i drukuje górę stosu, jeśli tak, lub znak nowej linii, jeśli nie, resetuje się bdo fałszowania, a następnie zachowuje działa, jeśli njeszcze nie został osiągnięty. MakroF , podane reguły, przechodzi przez całą tablicę w poszukiwaniu dopasowań. Zwiększa się o dwa, ponieważ nasze liczby całkowite i łańcuchy są wplecione przez tablicę, a po dopasowaniu wywołuje makro B. MakroBpo prostu pobiera ciąg (bieżąca pozycja w tablicy mniej niż jeden) i drukuje go. Ustawia się również bna prawdę. Nasz kompilator nie zadaje sobie trudu drukowania Bbez żadnych danych wejściowych i zasadniczo robi Fnop.


0

vim, 122 (kompilator) + 73 (pusty) + 90 (golf) + 123 (fizzbuzz) = 392 bajtów

Kompilator

:%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 wejściowy

3:Fizz
5:Buzz

Wygenerowany kod dla sprawy 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! %

Wygenerowany kod, opatrzony adnotacjami

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

Przykładowa sesja

$ 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

Podczas próby zdefiniowania i uruchomienia makra z innego makra dzieje się coś dziwnego. Jeśli uda mi się to rozwiązać, mogę zaoszczędzić kilka bajtów w stosunku do metody zapisu i źródła.
Ray

-2

SlooSarksi .Lang, 179

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

10
Nie znam tego języka; czy możesz nas link do strony opisującej to?
lirtosiast
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.