Menulis penerjemah brainfuck

18

Dalam bahasa pemrograman atau scripting apa pun x , tulis sebuah program yang mengambil kode sumber brainfuck yang valid dari stdin dan output, hingga stdout, kode sumber program, ditulis dalam bahasa x , yang akan menghasilkan hal yang persis sama seperti yang akan dilakukan oleh program brainfuck.

Program Anda harus bekerja untuk program brainfuck yang valid, termasuk file kosong.

Skor Anda akan sama dengan jumlah byte kode sumber Anda, ditambah jumlah byte output Anda diberi input berikut:

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

Misalnya, untuk input [-], output *p=0;jauh lebih menguntungkan daripadawhile(*p) *p--;

Jika Anda menggunakan karakter non-ASCII, jumlah byte harus dihitung menggunakan pengkodean UTF-8.

Skor terendah menang. Namun, solusi kreatif yang berupaya meminimalkan output harus didorong oleh peningkatan suara.

pengguna12205
sumber
11
Anda mungkin ingin menambahkan klausa bahwa bahasa target tidak juga di-brainfuck;)
Josh
@ Ya ampun, jika seseorang berhasil menulis program brainfuck pendek yang menghapus kode tidak berguna yang tidak perlu, mengapa tidak membiarkan mereka melakukannya?
user12205
2
Yah cukup sederhana karena solusi sepele keluaran sumber tidak berubah akan memiliki skor yang sangat rendah pula untuk brainfuck. Saya akan terkejut jika bahasa lain bisa mengalahkan itu.
Tim Seguine
@ Tim Seguine saya bisa mengubah pertanyaan, tetapi apakah itu tidak adil bagi mereka yang sudah memberikan jawaban? Dan jika saya mengubah pertanyaan, saya berpikir untuk mengubah perhitungan skor, membuatnya byte count of source + (byte count of output)^2, apakah itu akan mendorong orang untuk lebih fokus pada penyederhanaan hasil?
user12205
Umumnya mengubah pertanyaan seperti itu setelah sudah dijawab tidak disukai. Saya baru saja menunjukkan alasan mengapa saya pikir Josh benar. Baik untuk memposting hal-hal seperti ini di kotak pasir terlebih dahulu, sehingga Anda dapat mengatasi masalah potensial sambil bersikap adil kepada semua orang.
Tim Seguine

Jawaban:

12

Perl - 177 (sumber) + 172 (keluaran) = 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'

Menghitung shebang sebagai 2 byte, satu untuk setiap opsi. Pertama, masing-masing dari delapan perintah diterjemahkan ke dalam rentang p-w, sementara pada saat yang sama menghapus semua karakter lain. String ini kemudian dikodekan dengan run-length dan output dengan decoder / interpreter minimal. Beberapa hal dioptimalkan: string ><jelas tidak melakukan apa-apa, dan loop untuk yang mengikuti secara langsung setelah yang lain dapat dihapus seluruhnya, karena string tidak akan pernah dimasukkan.

Output untuk program uji:

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

Contoh dijalankan:

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

Perl - 232 (sumber) + 21 (keluaran) = 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\"")

Yang ini didasarkan pada pengamatan FIQ bahwa jika program asli tidak mengandung pernyataan input, output akan statis, dan karenanya dapat dikurangi menjadi satu printpernyataan. Jika Anda suka yang ini, pastikan untuk memberi jawabannya +1.

Jadi yang bisa kita lakukan adalah pipa stdout ke variabel, evalkode yang akan kita hasilkan, dan bungkus hasilnya menjadi a print.

... Tapi itu tidak akan selalu berhasil. Setiap kali kode yang akan diterjemahkan akan menghasilkan loop tak terbatas, (misalnya +[.]), ini tidak dapat direduksi menjadi satuprint pernyataan , karena alasan yang jelas. Jadi, sebagai gantinya, kami meluncurkan evalproses anak dengan batas waktu singkat, dan jika itu tidak selesai dieksekusi dalam waktu itu kami mengeluarkan program yang diterjemahkan seperti sebelumnya.

Terstruktur dan berkomentar:

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

Output untuk program sampel:

print"Hello\ world\!"

Output untuk ,[.]:

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

Output untuk +[.](setelah 9 detik):

eval'21647'=~s/./qw(--$ ++$ -- ++ print+chr$ $$i=ord+getc; while($$i){ })[$&].q($i;)/ger
primo
sumber
1
Ini luar biasa! Otaknya sakit :)
Timwi
Saya pikir wv.*?(?=w)itu salah. Saya pikir itu hanya akan menghapus kode hingga yang berikutnya ], tetapi Anda membutuhkannya untuk menemukan yang cocok ] ; Anda harus mengurus sarang ...
Timwi
@Timwi Tetap, dengan mengabaikan kasus bersarang wv[^v]*(?=w), yang secara signifikan lebih pendek daripada alternatifnya.
primo
14

Brainfuck, 5 + 540 = 545 byte

5 byte kode, 540 dari output file tes yang diberikan (dengan asumsi mendapat hitungan langsung dari tempel kode itu).

,[.,]

Dengan asumsi EOF adalah 0.

FIQ
sumber
@ primo karena tidak me-reset sebelum membaca interpreter yang tidak memiliki nilai pada EOF akan membuat program ini menjadi loop tanpa akhir untuk semua input yang lebih besar dari 0 byte.
Sylwester
Saya tidak dapat menahan diri untuk bertanya-tanya, perangkat lunak apa yang digunakan untuk menjalankan hal ini? xD
Teun Pronk
@TeunPronk Ada penerjemah brainfuck bernama bfi ( github.com/susam/bfi ). Kompilasi dan instal saja, dan jalankan seperti ini: di bfi input.bfmana input.bffile brainfuck akan ditafsirkan.
Braden Best
5

PHP, 553 + 27 = 580 byte

(553 byte dengan semua spasi putih, yaitu baris baru dan spasi, dihapus)

Saya payah sekali bermain golf PHP, jadi pendekatan ini bisa sangat dioptimalkan. Saya sebagian besar ingin menunjukkan pendekatan saya pada solusi dalam sesuatu yang bukan 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);

Pelaporan kesalahan harus dimatikan, jika tidak PHP akan membenci Anda. Penggunaan: buang ini sebagai halaman, dan jalankan dengan script.php? C = CODE (jika skrip yang dihasilkan membutuhkan input, Anda menjalankannya sebagai out.php? I = INPUT). Ingatlah untuk melepaskan url input!

Apa yang dilakukan pada dasarnya adalah ini - jika skrip BF berisi ",", cukup banyak embed dirinya sebagai skrip yang dihasilkan dengan $ b = 1; di atas. Jika TIDAK mengandung ",", itu mengoptimalkannya ke "echo '<BF output>'". Dengan mudah, skrip uji dalam OP TIDAK memerlukan input apa pun. The addlashes () ada di sana hanya untuk melarikan diri 'dan \.

FIQ
sumber
4

C ++, 695 + 510 = 1205 byte

Kode:

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

Keluaran:

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

Kode asli:

#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 << "}";
}
johnchen902
sumber
2

Python - 514 + 352 = 866

Kode:

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

Keluaran:

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

io

659 + 553 = 1212

Hal-hal seperti File standardInput readBufferOfLength(1)benar - benar membunuh jumlah byte tetapi saya tidak bisa mengatasinya. Saya tidak melakukan optimasi untuk simbol yang diulang atau kurangnya input dalam program BF, tetapi akan terus bekerja pada itu, juga bekerja pada satu yang memanfaatkan kemampuan pemrograman 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))

Pengujian

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

Hasil

Hello world!
659  +  553  = 1212
Jordon Biondo
sumber
1

Brainfuck , 109 + 407 = 516

>+[>+++++++[-<------>]<-[-[-[-[--------------[--[>+++++[-<------>]<+[--[[-]<[-]>]]]]]]]]<[.[-]]>>,[-<+<+>>]<]

Cobalah online!

Ini hanya menghapus operasi non BF dan tidak melihat optimasi lainnya.

Sylwester
sumber
0

Lua - 328 + 2256 = 2584

(Oh saya baru sadar Anda perlu menambahkan panjang hasilnya juga, skor buruk, sepertinya)

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

Diambil dari ini jawaban saya.

mniip
sumber
0

Lua - 319 + 21 = 340

Kemungkinan besar ini adalah kode terpendek dari semua, tetapi tidak menerima input, jadi agak curang. Saya mendapat ide untuk versi lain dengan masukan, lihat bagian akhir dari komentar ini.

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

Lua - 376 + 366 = 742

Versi ini untuk membuktikan bahwa lua dapat melakukan lebih baik dari 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;"}))()')

Kedua versi menambahkan 30000 byte data. Versi kedua saya didasarkan pada input / output: semuanya setelah '.' atau ',' akan dihapus. Versi kedua saya tidak memungkinkan loop tak terbatas ([.,], [], Dll.)

Ide saya adalah untuk mendapatkan:

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

Dari input Anda, dengan tambahan ', +.'

YoYoYonnY
sumber