เขียนนักแปล brainfuck


18

ในการเขียนโปรแกรมหรือภาษาสคริปต์xใด ๆให้เขียนโปรแกรมที่ใช้แหล่งข้อมูล brainfuck ที่ถูกต้องจาก stdin และเอาต์พุตไปยัง stdout ซอร์สโค้ดของโปรแกรมที่เขียนด้วยภาษาxซึ่งจะให้ผลลัพธ์เหมือนกับโปรแกรม brainfuck ที่แน่นอน

โปรแกรมของคุณต้องทำงานกับโปรแกรม brainfuck ที่ถูกต้องรวมถึงไฟล์เปล่า

คะแนนของคุณจะเท่ากับจำนวนไบต์ของซอร์สโค้ดของคุณบวกกับจำนวนไบต์ของเอาต์พุตของคุณตามอินพุตต่อไปนี้:

+++++ [-]
+++++ +++++ [
    > +++++ ++
    > ++ +++ ++++ +
    > +++
    <<< -
]
> ++ . 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
คุณอาจต้องการที่จะเพิ่มประโยคหนึ่งว่าภาษาเป้าหมายยังไม่เป็น brainfuck;)
จอช

@ จอชดีถ้ามีคนจัดการเขียนโปรแกรม brainfuck สั้น ๆ ที่เอารหัสไร้ประโยชน์ที่ไม่จำเป็นออกไปทำไมไม่ปล่อยให้พวกเขาทำ
user12205

2
ก็ค่อนข้างง่ายเพราะวิธีแก้ปัญหาเล็กน้อยของการแสดงผลแหล่งที่ไม่เปลี่ยนแปลงนั้นจะมีคะแนนต่ำมากต่อไปสำหรับ brainfuck ฉันจะแปลกใจถ้าภาษาอื่นสามารถเอาชนะได้
Tim Seguine

@ Tim Seguine ฉันสามารถเปลี่ยนคำถามได้ แต่นั่นจะไม่เป็นธรรมกับผู้ที่ได้ตอบคำถามไปแล้วหรือไม่? และถ้าฉันเปลี่ยนคำถามฉันกำลังคิดที่จะเปลี่ยนการคำนวณคะแนนทำให้เป็นbyte count of source + (byte count of output)^2เช่นนั้นจะกระตุ้นให้ผู้คนมุ่งเน้นไปที่การทำให้ผลลัพธ์ง่ายขึ้นหรือไม่
user12205

โดยทั่วไปการเปลี่ยนคำถามเช่นนั้นหลังจากที่ได้รับคำตอบแล้วจะขมวดคิ้ว ฉันแค่ชี้เหตุผลว่าทำไมฉันถึงคิดว่า Josh ถูก เป็นการดีที่จะโพสต์สิ่งต่างๆในกล่องทรายก่อนเพื่อให้คุณสามารถแก้ไขปัญหาที่อาจเกิดขึ้นได้ในขณะที่ทุกคนมีความยุติธรรม
Tim Seguine

คำตอบ:


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'

นับ shebang เป็น 2 ไบต์โดยหนึ่งตัวสำหรับแต่ละตัวเลือก ขั้นแรกคำสั่งแปดคำสั่งแต่ละคำจะถูกแปลลงในช่วงp-wขณะเดียวกันก็ลบอักขระอื่น ๆ ทั้งหมด สตริงนี้จะถูกเข้ารหัสความยาวและการส่งออกที่มีตัวถอดรหัส / ล่ามน้อยที่สุด บางสิ่งได้รับการปรับให้เหมาะสม: สตริง><ไม่ได้ทำอะไรเลยและสำหรับลูปที่ตามหลังโดยตรงอาจถูกลบทั้งหมดเนื่องจากจะไม่มีการป้อน

เอาต์พุตสำหรับโปรแกรมทดสอบ:

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ให้กับตัวแปร, โค้ดที่เราจะมีการส่งออกและการห่อผลในส่วนevalprint

... ที่ไม่ได้ผลเสมอไป เมื่อใดก็ตามที่รหัสที่จะแปลจะส่งผลให้เกิดการวนซ้ำไม่สิ้นสุด (เช่น+[.]) สิ่งนี้ไม่สามารถลดเป็น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
นี่มันอัศจรรย์มาก! สมองเจ็บ :)
Timwi

ฉันคิดว่าwv.*?(?=w)ผิด ฉันคิดว่ามันจะลบรหัสขึ้นต่อไป]แต่คุณจำเป็นต้องใช้มันเพื่อหาสิ่งที่จับคู่ ] ; คุณต้องดูแลการทำรัง ...
ทิมวี่

@Timwi คงที่โดยไม่สนใจกรณีที่ซ้อนกันwv[^v]*(?=w)ซึ่งสั้นกว่าทางเลือก
primo

14

Brainfuck, 5 + 540 = 545 ไบต์

โค้ดขนาด 5 ไบต์, 540 จากเอาต์พุตของไฟล์ทดสอบที่กำหนด (สมมติว่าได้ค่าที่ถูกต้องจากการวางโค้ดของฉัน)

,[.,]

สมมติว่า EOF คือ 0


@primo เนื่องจากไม่ได้รีเซ็ตก่อนที่จะอ่านล่ามที่ไม่มีค่า chaneg ที่ EOF จะทำให้โปรแกรมนี้วนซ้ำไม่รู้จบสำหรับอินพุตทั้งหมดที่มีขนาดใหญ่กว่า 0 ไบต์
Sylwester

ฉันไม่สามารถช่วยสงสัยได้ว่าซอฟต์แวร์ใดที่ใช้ในการเรียกใช้สิ่งนี้ xD
Teun Pronk

@TeunPronk มีล่ามสมองที่เรียกว่าbfi ( github.com/susam/bfi ) เพียงแค่รวบรวมและติดตั้งมันและใช้มันเพื่อต้องการ: bfi input.bfที่input.bfไฟล์ brainfuck ที่จะตีความ
Braden สุดยอด

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 แต่จะยังคงทำงานต่อไปเช่นเดียวกับการใช้ประโยชน์จากความสามารถในการ metaprogramming ของ 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

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

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

Lua - 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 ไบต์ รุ่นที่สองของฉันขึ้นอยู่กับอินพุต / เอาต์พุต: ทุกอย่างหลังจาก '.' หรือ ',' จะถูกลบ รุ่นที่สองของฉันไม่อนุญาตให้วนซ้ำไม่ จำกัด ([.,], [], ฯลฯ )

ความคิดของฉันคือการได้รับ:

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

จากการป้อนข้อมูลของคุณด้วยเครื่องหมายพิเศษ ', +.'

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.