FizzBu​​zzコンパイラーを作成する


17

コンパイラーゴルフの世界へようこそ。あなたの仕事は、仕様でFizzBu​​zzのバリアントを再生する別のプログラムを生成するプログラムを書くことです。

コンパイラー

FizzBu​​zzプログラムのバリアントを仕様に合わせて生成するコンパイラーを作成します。このバリアントの仕様は、整数/文字列のペアの配列の形式で表されます。

  • 入力は、言語に都合のよい形式であればどのような形式でもかまいません。(私の例ではn:xxxxを使用していますが、これは単に説明のためです。)
  • 各整数入力は、コンパイラーの呼び出しごとに1回のみ使用できます。
  • 各ペアの整数は、少なくとも1つの値を持ちます。
  • 各ペアの文字列は、ちょうど4つのASCII文字で構成されます。
  • 出力は、以下の規則に準拠する単一の完全なプログラムでなければなりません。
  • テキスト形式のプログラムである限り、出力は任意の便利な形式にすることができます。(したがって、ラムダ式を返しません。)

上記の規則に準拠していない入力の動作は未定義です。

生成されたFizzBu​​zzプログラム

コンパイラが生成するプログラムは、入力として単一の整数nを受け取ります。1からnまでの一連の数値を出力し、必要に応じて数値をFizzBu​​zz文字列に置き換えます。

  • 生成されたプログラムは、コンパイラーと同じ言語である必要があります。
  • 入力nは、言語に適した任意の形式にすることができます。
  • nには少なくとも1つの値があります。
  • コンパイラーへの整数入力の少なくとも1つの倍数である数値は、それらの整数を結合したすべてのストリングで置き換える必要があります。
  • FizzBu​​zz文字列に置き換えられない数値は、10進数のASCIIで出力する必要があります。

例えば;

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

得点

エントリーは、コンパイラーが生成するプログラムの長さをコンパイラーの長さに追加することによってスコアリングされます。以下の各パラメーターを使用してコンパイラーを何度も実行し、生成されたプログラムの長さとコンパイラーの長さを加算して、スコアを見つけます。

  1. ただカウント。(入力なし-生成されたプログラムは、置換なしで1からnまでカウントされます。)
  2. ただのゴルフ。(1:ゴルフ-生成されたプログラムは「ゴルフ」をn回出力します。)
  3. クラシックFizzBu​​zz。(3:フィズ、5:バズ)

(リストされているものだけでなく、有効な入力のコードを生成するためにコンパイラが必要なことに注意してください。)


コンパイラの長さのスコアはありませんか?
スパー

整数が1桁であると仮定できますか?文字列にスペースがないこと?
スパー14

@Sparrそれ(2桁の整数)は違いがありますか?スコアを作成するのは生成されたコードのみです。
billpg 14

まあ、fizzbuzzはインターネット上で既に非常に徹底的にゴルフされた問題です。私が試みた場合、それに対する解決策を読むことを忘れることができるかどうかはわかりません。
スパー14

1
最後に、AWKで実際に書くのが理にかなっているゴルフチャレンジ。
シャドウトーカー14

回答:


8

Python 3-168 162 + 230 = 392

ああ、Python、あなたは一生懸命努力しますがimport sys;sys.argv、4を掛けることは本当に痛いです!

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

出力プログラム:

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))
  • メインプログラムに期待される入力は、評価可能なPythonタプルのシーケンスまたは'()'入力なしです。(あなたが「便利」と言った。)例入力:'()''("Golf",1),''("Fizz",3),("Buzz",5)'注意シェルの引用符と1つの入力のためにコンマを末尾。

  • dict(未定義の順序付け!)からタプルに変更することによる午前1時の間違いを修正しました。

  • 他のプログラムに期待される入力は数だけです


あなたのコマンドライン引数の例では、二重引用符で囲み、「Fizz」と「Buzz」に単一引用符を使用する必要がありました-「 "{3: 'Fizz'、5: 'Buzz'}」のように、プログラムはまだ私にエラーを投げます。
ジェームズウィリアムズ14

エラーは何ですか?
ジェイソンS

@JasonS-こんにちは。この挑戦の経験に興味があります。meta.codegolf.stackexchange.com/questions/5050/…– billpg 15
17:06に

6

perl6 376 340 84 + 115 = 199

UPDATE:取得するにはPerl6のにperl5の切り替えsayなしuse feature

更新:5つではなく3つのテストケース

FizzBu​​zzには既に何百ものゴルフのソリューションがあり、多くのコンテストが同じ結果で終わっているので、そこから始めました。私のコンパイラは、そのソリューションのカスタマイズされたバージョンを作成するだけです。「ジャストカウント」バリエーションを考慮して、いくつかの余分な文字が挿入されました。

コンパイラ、次のような引数が必要です: "Fizz 3" "Buzz 5"

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

コンパイルされたプログラム、次のような引数が必要です:100

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

古いテストケース用にコンパイルされたプログラム:

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

質問のコメントで説明されているように、規則を変更しました。スコアを再計算する必要があります。
billpg 14

@billpg完了、改善:)
スパー14

こんにちは。この挑戦の経験に興味があります。meta.codegolf.stackexchange.com/questions/5050/...
billpg

3

パイス-51 +(38 + 43 + 50)= 182バイト

おそらくコンパイラーを数バイトゴルフできます。それらすべてのリンクは、オンライン通訳へのパーマリンクです。

コンパイラ -51バイト

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

入力タプルで文字列の書式設定を行うだけです。次のような入力を受け取ります。

3 5
Fizz Buzz

なし -38バイト

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

ちょうどゴルフ -43バイト

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

クラシックフィズバズ -50バイト

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

2

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

ここへの最初の参加は、この挑戦​​は最も難しいものではないので、試してみたいと思いました。ただし、C ++を使用し、C ++ 11を追加しても、かなり冗長な言語ですが、改善の余地があると確信しています。

コンパイラ(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;}

3Fizz 5Buzzetc の形式の引数を想定しています。

カウント(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";}}

ゴルフ(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";}}

FizzBu​​zz(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";}}

追加情報

GCC 4.8.1でテストされ、コンパイラーはチートしません。

テストケースの生成を自動化して実行するための小さなメイクファイルを次に示します(使用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

こんにちは。この挑戦の経験に興味があります。meta.codegolf.stackexchange.com/questions/5050/…– billpg 15
17:06に

map<int,string> f可能性がありますmap<int,string>fj=1で同時に初期化できますz
Yytsi

2

ルビー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}"

使用法:

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

スタックス、23 + 5 + 17 + 29 = 74

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

実行してデバッグする

これまでの最短回答驚くことではないが、ゼリーにbyられた。Staxで提供される文字列テンプレートは本当にすてきで、printfのような機能を提供します。コンパイラーによって生成されるプログラムは、ほとんどの場合、パッキングを使用せずに手動でコードゴルフを行うことで達成できる最高のプログラムと同じくらい短いです。

コンパイラ自体の長さは23 バイトです。

ASCIIに相当するものは次のとおりです。

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

入力を提供し[]、これを生成します(5バイト)

mzc_?

実行してデバッグする

入力を提供し[[1,"Golf"]]、これを生成します(17バイト)

mz_1%z"Golf"?+c_?

実行してデバッグする

入力を提供し[[3,"Fizz"],[5,"Buzz"]]、これを生成します(29バイト)

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

実行してデバッグする


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

私は他の答えを取り入力パラメーターを追加しながら準引用符で囲みました。結果のフォームを単一行として印刷し、不要な空白文字を削除します。コンパイラは以前のバージョンよりも少し長くなりますが、結果のスコアは減少します。

スコア

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

返される値:

574
(215 111 119 129)

可愛い

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

入力形式は、(number string)カップルのリストです。例えば:

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

...標準出力に出力します:

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

...きれいに印刷されています:

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

結果の関数のテスト:

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


1

ゼリー88 84 83 73バイト

これまでの最短回答(前の「最短回答」に1バイトのビート)

コンパイラ:

Ṿ€“ḍ@€“ẋ"ЀF€ȯ"”jµFF?⁾RY

オンラインでお試しください!(コンパイラ)

オンラインでお試しください!(バイトカウントを確認)


統計:

19 24コンパイラ
   20ゴルフ
17   2カウント
   27 fizzbuzz
合計83 73

beatられているのを見てうれしい。
ウェイジュン周

0

C、合計1080バイト

コンパイラ[369バイト]

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

フィズバズ[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);}

ゴルフ[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);}

カウント[233バイト]

#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バイト

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

オンラインでお試しください!

コンパイラへの入力(168バイト)は、整数、文字列、整数、文字列などとしてスタックに配置する必要があります(3 [Fizz] 5 [Buzz])。フィズとバズを印刷したい順序で指定する必要がありますが、これはちょっとしたチートかもしれません(dc以前にバブルソートを実装していたため、約100バイトかかると思います)たとえば、「Fizz」は3で、「Buzz」は5で実行されますが、15は「BuzzFizz」を生成します。

これはもう少しゴルフできると確信しています。最終プログラムのメインマクロ(M)は、入力がなければ不必要な2つのマクロ(FおよびP)に依存します。現在、コンパイラは、これらのマクロの異なる(はるかに小さい)バージョンがない場合、入力と出力をチェックしますが、セットアップ全体が最適かどうかはわかりません。

コンパイラ自体は非常に単純で、スタックに「ルール」があるかどうかを確認するだけで、スタックの深さを格納するコードを出力する場合z、0インデックス付き配列にスタックを格納しますaに、一般化されたFizzBu​​zzコード。スタックに何もなかった場合、実際にはFizzBu​​zzコードの修正バージョンを出力するだけです。テストケース:

入力なし(46バイト):

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

3 [Fizz] 5 [Buzz](117バイト):

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 [ゴルフ](103バイト):

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

それらはすべてスタック上のn値を期待し、これはに保存されnます。「ルール」を持つものはa、奇数インデックスの文字列と偶数の整数で配列に配置します。メインマクロMは、スタック上のすべてのものをインクリメントしF、値を配列aと照合するマクロを実行し、Fレジスタbを真偽に設定するかどうかを確認し、そうであればスタックの最上部を印刷し、そうでない場合は改行bを出力し、偽にリセットしてから保持しますnまだ到達していない場合は、自身を実行します。マクロはF、与えられた規則に従って、配列全体を検索して一致を探します。整数と文字列が配列全体に織り込まれているため、2ずつ増加し、一致するとmacroを呼び出しますB。大きいB文字列(配列内の現在位置から1を引いたもの)を取得し、それを出力します。またb、真実に設定します。コンパイラーはB、入力なしで印刷することをせず、基本的にFnopを作成します。


0

vim、122(コンパイラ)+ 73(空)+ 90(ゴルフ)+ 123(フィズバズ)= 392バイト

コンパイラ

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

入力形式

3:Fizz
5:Buzz

FizzBu​​zzケース用に生成されたコード

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

生成されたコード、注釈付き

# 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です。

セッション例

$ 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

別のマクロ内からマクロを定義して実行しようとすると、奇妙なことが起こります。私がそれを整理することができれば、保存とソースのアプローチに比べて数バイト節約するかもしれません。
レイ

-2

SlooSarksi .Lang、179

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

10
私はこの言語に精通していません。それを説明するページにリンクしていただけますか?
リスト管理者
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.