Brainfuckトランスレーターを書く


18

任意のプログラミング言語またはスクリプト言語xで、有効なBrainfuckソースコードをstdinから取得し、brainfuckプログラムとまったく同じ結果を出力する言語xで記述されたプログラムのソースコードをstdoutに出力するプログラムを作成します。

プログラムは、空のファイルを含む、有効なブレインファックプログラムで動作する必要があります。

スコアは、ソースコードのバイトカウントと、次の入力が与えられた場合の出力のバイトカウントに等しくなります。

+++++ [-]
+++++ +++++ [
    > +++++ ++
    > ++ +++ ++++ +
    > +++
    <<< -
]
> ++ . H
> + . e
++ +++ ++. l
. l
+++ . o
> ++ . space
< +++++ +++ . w
----- --- . o
+++ . r
---- - - . l
----- --- . d
> + . exclamation mark
------lol; useless code :-)--------------------------[.............................................][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][][]<-<<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><

たとえば、の入力の[-]場合、の出力は*p=0;while(*p) *p--;

非ASCII文字を使用する場合は、UTF-8エンコードを使用してバイトカウントを計算する必要があります。

最低スコアが勝ちます。ただし、出力を最小化しようとする創造的なソリューションは、賛成票によって奨励されるものとします。


11
ターゲット言語もブレインファックではないという節を追加したいかもしれません;)
ジョシュ14

@Joshさん、不必要な無駄なコードを削除する短いブレインファックプログラムを誰かが書いたのなら、なぜそれをさせないのですか?
user12205 14

2
ソースを変更せずに出力するという些細な解決策は、とにかくブレインファックのスコアが非常に低いためです。別の言語がそれを打ち負かすことができれば、私は驚くでしょう。
ティムセギーン14

@Tim Seguine質問を変更することはできますが、すでに回答を提供した人にとっては不公平でしょうか?質問を変更する場合、スコア計算を変更してbyte count of source + (byte count of output)^2、それを行うことについて考えています
user12205 14

一般的に、そのような質問を既に回答された後に変更することは眉をひそめます。私はジョシュが正しかったと思う理由を指摘していました。このようなものを最初にサンドボックスに投稿するのは良いことです。そうすることで、潜在的な問題を解決することができます。
ティムセギーン14

回答:


12

Perl-177(ソース)+ 172(出力)= 349

#!perl -p0
y/-+><.,[]
-~/p-w/d;s/(.)\K\1+|rs|wv[^v]*(?=w)/$+&&length$&/ge;$_="eval'r$_'=~".'s/.(\d*)/(qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&&v63].q($i;))x($++1)/ger'

各オプションに1つずつ、2バイトとしてシバンをカウントします。まず、8つのコマンドのそれぞれがrange p-wに変換され、同時に他のすべての文字が削除されます。この文字列は、ランレングスでエンコードされ、最小限のデコーダー/インタープリターで出力されます。いくつかのことが最適化されています。文字列は><明らかに何もしません。また、次の直後に続くforループは入力されないため、完全に削除されます。

テストプログラムの出力:

eval'rq4vpwq9vrq6rq9rq2s2pwrq1trqtq6t1q2trq1tsq7tp7tq2tp5tp7trqtp32vt44wsps1'=~s/.(\d*)/(qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&&v63].q($i;))x($++1)/ger

サンプル実行:

$ perl brainfusk.pl < in.bf | perl
Hello world!

Perl-232(ソース)+ 21(出力)= 253

#!perl -p0
y/-+><.,[]
-~/0-7/d;$_="eval'2$_'=~".'s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger';
/5/||fork?(wait,$?||exit):($SIG{ALRM}=sub{exit 1},alarm 9,$S=select(open 1,'>',\$o),eval,print$S "print\"\Q$o\E\"")

これは、元のプログラムに入力ステートメントが含まれていない場合、出力は静的であるため、単一のステートメントに減らすことができるというFIQの観察に基づいていますprint。これが気に入ったら、彼の答えに+1してください。

したがって、できることはstdout、変数にパイプし、eval出力するコードで、結果をにラップすることprintです。

...しかし、常に機能するとは限りません。翻訳するコードは無限ループに生じるであろうたびに、(例えば+[.])、これはできませんシングルに減少させることがprint明白な理由のために、声明。代わりに、eval短いタイムアウトで子プロセスでを起動し、その時間内に実行が終了しない場合、以前のように翻訳されたプログラムを出力します。

構造化およびコメント化:

if(!/5/) { # no `,` in program

  if(fork) { # parent process

    # wait for child
    wait;
    # no child error, terminate without output
    $?||exit

  } else { # child process

    # alarm handler, exit with error
    $SIG{ALRM}=sub{exit 1};
    # set an alarm in 9 seconds
    alarm 9;
    # redirect STDOUT to variable $o
    $S=select open 1,'>',\$o;
    # execute translated code
    eval;
    # wrap the result in a print statement
    print$S "print\"\Q$o\E\""
  }
}

サンプルプログラムの出力:

print"Hello\ world\!"

の出力,[.]

eval'25647'=~s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger

出力+[.](9秒後):

eval'21647'=~s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger

1
これは素晴らしいです!脳が痛い:)
ティムウィ14

wv.*?(?=w)は間違っていると思います。次までコードを削除するだけだと思い]ますが、一致 するものを見つけるために必要]です。あなたは...ネストの世話をする必要がある
Timwi

@Timwi修正、ネストされたケースを無視することによりwv[^v]*(?=w)、代替よりも大幅に短くなりました。
プリモ14

14

Brainfuck、5 + 540 = 545バイト

5バイトのコード、所定のテストファイルの出力から540(そのコードの貼り付けからカウントが正しいと仮定した場合)。

,[.,]

EOFが0であると仮定します。


@primoは、EOFで値を変更しないインタープリターを読み取る前にリセットされないため、このプログラムは0バイトより大きいすべての入力に対して無限ループになります。
シルウェスター14

私はこのソフトウェアを実行するためにどのソフトウェアが使用されているのか疑問に思いませんか?xD
テウンプロンク14

@TeunPronk bfigithub.com/susam/bfi)というBrainfuckインタープリターがあります。ただ、コンパイルしてインストールし、そしてそのようにそれを実行します:bfi input.bfどこをinput.bfbrainfuckファイルが解釈されるべきです。
ブレーデンベスト14

5

PHP、553 + 27 = 580バイト

(すべての空白、つまり改行とスペースが削除された553バイト)

PHPでゴルフをするのはひどいことなので、このアプローチは大幅に最適化できます。私は主にBFではない何かでソリューションへのアプローチを示したかったです。

<?php
echo "<?php ";
$x = 'if (!$b) $c = $_GET[c];
$x=$y=$n[0]=$p=0;$o[0]=1;$d="";
while($a=$c[$x++]){
    if($o[$p]){
        if($a=="-")$m[$y]--;
        if($a=="+")$m[$y]++;
        $m[$y]=$m[$y]%256;
        if($a=="<")$y--;
        if($a==">")$y++;
        if($a=="."){
            $e=chr($m[$y]);
            if ($b) echo $e;
            else $d.=addslashes($e);
        }
        if($a==",")$m[$y]=($b=$_GET[i])?ord($b):0;
    }if($a=="["){
        $p++;
        $n[$p]=$x-1;
        $o[$p]=$o[$p-1]?$m[$y]:0;
    }
    if($a=="]"){
        if($o[$p])$x=$n[$p];
        $p--;
        if($p=-1)$p=0;
    }
}
if (!$b) echo "echo \'$d\';";';
if (strstr($_GET['c'],",")) {
    $x = '$b=1;'.$x;
    echo '$c="'.addslashes($_GET[c]).'";'.$x;
    return;
}
eval($x);

エラー報告はオフにする必要があります。オフにしないと、PHPはあなたを嫌います。使用法:これをページとしてスローし、script.php?c = CODEで実行します(結果のスクリプトに入力が必要な場合は、out.php?i = INPUTとして実行します)。入力をURLエスケープすることを忘れないでください!

これは基本的にこれです-BFスクリプトに「、」が含まれている場合、結果として、$ b = 1が付加されたスクリプトとして埋め込まれます。頂点で。「、」が含まれていない場合、「echo '<BF output>'」まで最適化されます。便利なことに、OPのテストスクリプトは入力を必要としません。addlashes()は、 'と\をエスケープするためにあります。


4

C ++、695 + 510 = 1205バイト

コード:

#include<iostream>
#include<utility>
#include<vector>
#define D "\n#define "
using namespace std;using S=string;int main(){vector<pair<S,S>>m={{"--------","(*p)-=8;"},{"<>",""},{"[]","F;"},{"+","A;"},{"-","B;"},{">","C;"},{"<","D;"},{"[","F{"},{"]","}"},{".","E;"},{",","std::cin>>*p;"}};S s;char c;while(cin>>c)if(S("+-><[].,").find(c)<8)s+=c;for(int i=0;i<s.length();i++)if(s.substr(i,4)=="[][]")s=s.replace(i--,4,"[]");cout<<"#include<iostream>" D"A ++*p" D"B --*p" D"C p++" D"D p--" D"E std::cout<<*p" D"F while(*p)\nint main(){char*p=new char[1<<19]();";while(s.size())for(auto p:m)if(s.substr(0,p.first.length())==p.first){s=s.substr(p.first.length());cout<<p.second;break;}cout<<"}";}

出力:

#include<iostream>
#define A ++*p
#define B --*p
#define C p++
#define D p--
#define E std::cout<<*p
#define F while(*p)
int main(){char*p=new char[1<<19]();A;A;A;A;A;F{B;}A;A;A;A;A;A;A;A;A;A;F{C;A;A;A;A;A;A;A;C;A;A;A;A;A;A;A;A;A;A;C;A;A;A;D;D;D;B;}C;A;A;E;C;A;E;A;A;A;A;A;A;A;E;E;A;A;A;E;C;A;A;E;D;A;A;A;A;A;A;A;A;E;(*p)-=8;E;A;A;A;E;B;B;B;B;B;B;E;(*p)-=8;E;C;A;E;(*p)-=8;(*p)-=8;(*p)-=8;(*p)-=8;B;F{E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;E;}F;D;B;D;D;}

元のコード:

#include <iostream>
#include <utility>
#include <vector>
using namespace std;
int main() {
    vector<pair<string, string>> m={
    {"--------","(*p)-=8;"},
    {"<>",""},
    {"[]","F;"},
    {"+","A;"},
    {"-","B;"},
    {">","C;"},
    {"<","D;"},
    {"[","F{"},
    {"]","}"},
    {".","E;"},
    {",","std::cin>>*p;"}};
    string s;
    char c;
    while (cin >> c)
        if (string("+-><[].,").find(c) < 8)
            s += c;
    for(int i = 0; i < s.length(); i++)
        if(s.substr(i, 4) == "[][]")
            s = s.replace(i--, 4, "[]");
    cout << "#include<iostream>\n"
            "#define A ++*p\n"
            "#define B --*p\n"
            "#define C p++\n"
            "#define D p--\n"
            "#define E std::cout<<*p\n"
            "#define F while(*p)\n"
            "int main(){char*p=new char[1<<19]();";
    while (s.size())
        for (auto p : m)
            if (s.substr(0, p.first.length()) == p.first) {
                s = s.substr(p.first.length());
                cout << p.second;
                break;
            }
    cout << "}";
}

2

Python-514 + 352 = 866

コード:

import sys,zlib,base64
s,i="import sys\na,i=[0]*300000,0\n",0
for c in sys.stdin.read():
 if c in"+-><,.[]":
  s+=" "*i+{'+':"a[i]+=1\n",'-':"a[i]-=1\n",'>':"i+=1\n",'<':"i-=1\n",',':"a[i]=(lambda x:0if x==''else ord(x))(sys.stdin.read(1))\n",".":"sys.stdout.write(chr(a[i]))\n","[":"while a[i]!=0:\n","]":"pass\n"}[c]
  i+={'[':1,']':-1}.get(c,0)
print('import zlib,base64\nexec(zlib.decompress(base64.b64decode("'+base64.b64encode(zlib.compress(bytes(s,"utf8"),9)).decode("utf8")+'")).decode("utf8"))')

出力:

import zlib,base64
exec(zlib.decompress(base64.b64decode("eNrLzC3ILypRKK4s5krUybSNNojVMjYAAR0DrsTozFhtW0OCdHlGZk6qAoinaGtgxQVm6QLFFQoSi4uJNoVc2zJBggowWTIZVDGEEvMzddFJ1FDMxBYUwFjTKy5JyS8t0SsvyixJ1UjOKNIASWpqomrAp5DceMBnJjn2Ee0ZojToUiGlEfIFzA5yaGqHELXtp5XfMukVwMOFRi/u8IXZqOSo5KjkqOSIlAQ3k9BLy1HBUcFRwVFBOgpmIrfeMhGE9ihrpLEAudg3NA==")).decode("utf8"))

1

io

659 + 553 = 1212

File standardInput readBufferOfLength(1)バイトカウントを本当に殺すようなものですが、私はそれを回避することはできません。BFプログラムで繰り返されるシンボルや入力不足の最適化は行いませんでしたが、引き続き作業を続け、ioのメタプログラミング機能を利用した作業も行います。

"v :=Vector clone setSize(30000)
p :=0
z :=getSlot(\"method\")
j :=z(p=p+1)
k :=z(p=p-1)
a :=z(v at(p))
l :=z(v atPut(p,a+1))
m :=z(v atPut(p,a-1))
n :=z(a asCharacter print)
u :=getSlot(\"while\")
o :=z(v atPut(p,File standardInput readBufferOfLength(1)))"println
z :=getSlot("method")
g :=z(a,b,if(a,a,b))
v :=z(e,f,if((x :=s)==e,nil,f .. g(w(x),"")))
s :=z(File standardInput readBufferOfLength(1))
w :=z(c,c switch(">",v("<","j"),"<","k","+","l","-","m",".","n",",","o","[",v("]","u(a>0,"),"]",")"))
while((c :=s)!=nil,if((t :=w(c))!=nil,t println))

テスト中

cat test.bf | io bftrans.io > out.io && io out.io && echo && echo  $(cat out.io | wc -c) " + " $(cat bftrans.io | wc -c) " = "$(($(cat bftrans.io | wc -c) + $(cat out.io | wc -c)))

利回り

Hello world!
659  +  553  = 1212


0

ルア-328 + 2256 = 2584

(ああ、私はちょうどあなたが結果の長さも追加する必要があることに気づきました、悪いスコア、それは次のように見えます)

print((("l,m,p=loadstring,{0},1 z,y,x,w,v,u=l'io.write(string.char(@))',l'@=io.read(1):byte()',l'p=p-1',l'p=p+1 @=@or 0',l'@=(@+1)%256',l'@=(@-1)%256'"..io.read"*a":gsub("[^.,<>[%]+-]",""):gsub(".",{["."]="z()",[","]="y()",["<"]="x()",[">"]="w()",["["]="while @~=0 do ",["]"]="end ",["+"]="v()",["-"]="u()"})):gsub("@","m[p]")))

私のこの答えから取った。


0

ルア-319 + 21 = 340

これはおそらくすべての中で最も短いコードですが、入力を受け付けないため、ちょっとカンニングです。入力のある別のバージョンのアイデアがありました。このコメントの最後をご覧ください。

loadstring("o=\"\";d={"..string.rep("0,",30000).."}p=1;"..io.read():gsub("[^%+%-<>%.,%[%]]+",""):gsub(".",{["+"]="d[p]=d[p]+1;",["-"]="d[p]=d[p]-1;",[">"]="p=p+1;",["<"]="p=p-1;",["."]="o=o..string.char(d[p])",[","]="d[p]=io.read()",["["]="while d[p]~=0 do ",["]"]="end;"}))()print("print("..string.format("%q",o)..")")

ルア-376 + 366 = 742

このバージョンは、luaが2584より優れていることを証明するためのものです:D

print('loadstring("d={"..string.rep("0,",30000).."}p=1;"..('..string.format("%q",io.read():gsub("[^%+%-<>%.,%[%]]+",""):gsub("%[[^%+%-<>%,%[%]]*%]",""):match("(.*[.,]).-"))..'):gsub(".",{["+"]="d[p]=d[p]+1;",["-"]="d[p]=d[p]-1;",[">"]="p=p+1;",["<"]="p=p-1;",["."]="io.write(string.char(d[p]))",[","]="d[p]=string.byte(io.read())",["["]="while d[p]~=0 do ",["]"]="end;"}))()')

どちらのバージョンも30000バイトのデータを追加します。2番目のバージョンは、入力/出力に基づいています。「。」の後のすべて または「、」が削除されます。2番目のバージョンでは、無限ループ([。、]、[]など)は許可されません

私のアイデアは取得することです:

print("Hello world!"..string.char(string.byte(io.read())+1)

入力から、追加の「、+」を使用

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.