Brainfuck tercümanı yazın


18

Herhangi bir programlama veya kodlama dilinde x , stdin ve çıktıdan geçerli bir brainfuck kaynak kodunu alan, x dilinde yazılmış bir programın kaynak kodunu, brainfuck programının yaptığıyla aynı şeyi veren bir program yazın.

Programınız, boş dosya da dahil olmak üzere geçerli herhangi bir brainfuck programı için çalışmalıdır.

Puanınız, kaynak kodunuzun bayt sayısına ve aşağıdaki giriş verildiğinde çıktınızın bayt sayısına eşit olacaktır:

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

Örneğin, bir girişi için [-],*p=0; çok daha elverişlidir.while(*p) *p--;

ASCII olmayan karakterler kullanırsanız, bayt sayısı UTF-8 kodlaması kullanılarak hesaplanmalıdır.

En düşük puan kazanır. Ancak, çıktıyı en aza indirmeye çalışan yaratıcı çözümler, oylar tarafından teşvik edilecektir.


11
Hedef dilin de beyinsiz olmadığı bir madde eklemek isteyebilirsiniz;)
Josh

@Josh, eğer birisi gereksiz gereksiz kodları kaldıran kısa bir brainfuck programı yazmayı başardıysa, neden yapmasına izin vermiyorsunuz?
user12205

2
Oldukça basit bir şekilde, kaynağı değiştirmeden çıkmanın önemsiz çözümü beyin fırtınası için zaten çok düşük bir puana sahip olacak. Başka bir dil bunu yenebilirse şaşıracağım.
Tim Seguine

@Tim Seguine Soruyu değiştirebilirim, ama bu zaten bir cevap vermiş olanlar için haksızlık olur mu? Ve soruyu değiştirirsem, skor hesaplamasını değiştirmeyi, yapmayı düşünüyorum byte count of source + (byte count of output)^2, bu da insanları çıktıyı basitleştirmeye daha fazla odaklanmaya teşvik eder mi?
user12205

Genellikle böyle bir soruyu daha sonra cevaplandıktan sonra değiştirmek hoş karşılanmaz. Josh'un haklı olduğunu düşündüğüm bir nedeni işaret ediyordum. Öncelikle kum havuzunda böyle şeyler yayınlamak iyidir, böylece herkes için adil olurken potansiyel sorunları çözebilirsiniz.
Tim Seguine

Yanıtlar:


12

Perl - 177 (kaynak) + 172 (çıktı) = 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'

Her seçenek için bir tane, 2 bayt olarak sayma. İlk olarak, sekiz komutun her biri aralığa çevrilirken p-waynı zamanda diğer tüm karakterler kaldırılır. Bu dize daha sonra çalışma uzunluğu kodlanır ve minimum bir kod çözücü / yorumlayıcı ile çıkar. Birkaç şey optimize edildi: dize>< açıkçası hiçbir şey yapmıyor ve doğrudan diğerinden sonra gelen bir for döngüsü, asla girilmeyeceği için tamamen kaldırılabilir.

Test programı çıktısı:

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

Örnek bir çalışma:

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

Perl - 232 (kaynak) + 21 (çıkış) = 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\"")

Bu, FIQ'nun orijinal program bir girdi deyimi içermiyorsa, çıktının statik olacağı ve dolayısıyla tek bir printdeyime indirilebileceği gözlemine dayanır . Bunu beğendiyseniz , cevabını verdiğinizden emin olun +1 .

Yapabileceğimiz şey, stdoutbir değişkene, evalçıktıya sahip olacağımız koda ve sonucu birprint .

... bu her zaman işe yaramayacak. Çevrilecek kod sonsuz döngüye neden olurdu zaman, (örneğin +[.]), bu olamaz , tek indirgenemez printbilinen nedenlerle, deyimi. Bunun yerine, evalkısa bir zaman aşımı ile bir alt süreçte başlatıyoruz ve eğer bu süre içinde yürütmeyi bitirmezse, çevrilmiş programı daha önce olduğu gibi çıkarırız.

Yapısal ve yorumlu:

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

Örnek program için çıktı:

print"Hello\ world\!"

Çıktı ,[.]:

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

Çıkış +[.](9 saniye sonra):

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

1
Bu harika! Beyin ağrıyor :)
Timwi

Bence wv.*?(?=w)yanlış. Ben sadece bir sonraki kadar kodu kaldıracak düşünüyorum ], ama eşleşen bulmak için ihtiyacınız ]; yuvalama dikkat ...
Timwi

@Timwi wv[^v]*(?=w)Alternatiften önemli ölçüde daha kısa olan iç içe geçmiş vakaları göz ardı ederek düzeltildi .
primo

14

Brainfuck, 5 + 540 = 545 bayt

5 bayt kod, verilen test dosyasının çıktısından 540 (bu kodu yapıştırmamdan sayıyı aldığını varsayarak).

,[.,]

EOF varsayıldığında 0.


@primo, EOF'daki değeri değiştirmeyen bir tercümanı okumadan önce sıfırlamadığından, bu programı 0 bayttan büyük tüm girişler için sonsuz bir döngü haline getirecektir.
Sylwester

Merak edemiyorum, bu şeyleri çalıştırmak için hangi yazılım kullanılıyor? xD
Teun Pronk

@TeunPronk bfi ( github.com/susam/bfi ) adında bir beyin fırtınası yorumlayıcısı var . Sadece derleyin ve yükleyin ve böyle çalıştırın: yorumlanacak brainfuck dosyası bfi input.bfnerede input.bf.
Braden Best

5

PHP, 553 + 27 = 580 bayt

(Tüm boşluklar, yani satırsonu ve boşluklar kaldırılmış 553 bayt)

Ben PHP golf kötü emmek, bu yüzden bu yaklaşım yoğun bir şekilde optimize edilebilir. Çözüme yaklaşımımı çoğunlukla BF olmayan bir şeyde göstermek istedim.

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

Hata bildirimi kapalı olmalıdır, aksi takdirde PHP sizden nefret eder. Kullanımı: bunu bir sayfa olarak atın ve script.php? C = CODE ile çalıştırın (sonuçta ortaya çıkan komut dosyası girdi gerektiriyorsa, out.php? İ = INPUT olarak çalıştırırsınız). Url giriş kaçış unutmayın!

Bunun yaptığı temelde budur - eğer BF betiği "," içeriyorsa, hemen hemen ekli $ b = 1 ile sonuçlanan betiğe gömülür; tepede. "," İÇERMEZSE, onu "echo '<BF output>'" olarak optimize eder. Uygun bir şekilde, OP'deki test komut dosyası herhangi bir giriş gerektirmez. Addslashes () sadece 've \' den kaçmak içindir.


4

C ++, 695 + 510 = 1205 bayt

Kod:

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

Çıktı:

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

Orijinal kod:

#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

Kod:

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

Çıktı:

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

1

io

659 + 553 = 1212

File standardInput readBufferOfLength(1)Bayt sayısını gerçekten öldürmek gibi şeyler var , ancak bunun üstesinden gelemiyorum. BF programında tekrarlanan semboller veya girdi eksikliği için optimizasyon yapmadım, ancak üzerinde çalışmaya devam edeceğim, ayrıca io'nun metaprogramlama yeteneklerini kullanan biri üzerinde çalışacağım.

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

Test yapmak

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

Verim

Hello world!
659  +  553  = 1212

1

Brainfuck , 109 + 407 = 516

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

Çevrimiçi deneyin!

Sadece BF olmayan op'ları kaldırır ve diğer optimizasyonlara bakmaz.


0

Lua - 328 + 2256 = 2584

(Oh, sadece sonucun uzunluğunu da eklemeniz gerektiğini fark ettim, düşük puan, benziyor)

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

Bu cevabımdan alındı .


0

Lua - 319 + 21 = 340

Bu muhtemelen en kısa koddur, ancak girişi kabul etmez, bu yüzden biraz daha ucuzdur. Girişli başka bir sürüm için bir fikrim var, bu yorumun sonuna bakın.

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

Bu sürüm, lua'nın 2584: D'den daha iyi yapabileceğini kanıtlamak içindir.

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

Her iki sürüm de 30000 bayt veri ekler. İkinci versiyonum girdi / çıktıya dayanıyor: her şey bir '.' veya ',' kaldırılacak. İkinci sürümüm sonsuz döngülere izin vermiyor ([.,], [], Vb.)

Benim fikrim:

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

Girişinizden ekstra bir ', +' ile.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.