Napisz tłumacza pieprzonego mózgu


18

W dowolnym języku programowania lub skryptowym x napisz program, który pobiera prawidłowy kod źródłowy skoku mózgowego ze standardowego wyjścia i wyjścia, do standardowego kodu źródłowego programu napisanego w języku x , który wygenerowałby dokładnie to samo, co zrobiłby ten program.

Twój program musi działać dla każdego prawidłowego programu do pieprzenia mózgu, w tym pustego pliku.

Twój wynik byłby równy liczbie bajtów kodu źródłowego oraz liczbie bajtów danych wyjściowych przy następujących danych wejściowych:

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

Na przykład dla wejścia [-]wartość wyjściowa *p=0;jest znacznie bardziej korzystna niżwhile(*p) *p--;

Jeśli zdarzy ci się używać znaków spoza ASCII, liczbę bajtów należy obliczyć przy użyciu kodowania UTF-8.

Najniższy wynik wygrywa. Jednak kreatywne rozwiązania, które próbują zminimalizować wyniki, będą zachęcane przez entuzjastów.


11
Możesz dodać klauzulę, że językiem docelowym też nie jest pieprzenie mózgów;)
— Josh

@Josh cóż, jeśli komuś udało się napisać krótki program do pieprzenia mózgu, który usuwa niepotrzebne niepotrzebne kody, dlaczego nie pozwolić mu tego zrobić?
— user12205

2
Cóż, po prostu dlatego, że trywialne rozwiązanie przekazywania niezmienionego źródła i tak będzie miało naprawdę niski wynik za pieprzenie mózgu. Będę zaskoczony, jeśli inny język da sobie radę.
— Tim Seguine

@Tim Seguine Mógłbym zmienić pytanie, ale czy byłoby to niesprawiedliwe wobec tych, którzy już udzielili odpowiedzi? A jeśli zmienię pytanie, myślę o zmianie sposobu obliczania wyniku byte count of source + (byte count of output)^2, czy to zachęciłoby ludzi do większego skupienia się na uproszczeniu wyników?
— user12205

Zasadniczo zmiana takiego pytania po udzieleniu odpowiedzi jest niezadowolona. Właśnie wskazałem powód, dla którego uważam, że Josh miał rację. Dobrze jest najpierw umieszczać takie rzeczy w piaskownicy, abyś mógł rozwiązywać potencjalne problemy, zachowując przy tym sprawiedliwość wobec wszystkich.
— Tim Seguine

Odpowiedzi:


12

Perl - 177 (źródło) + 172 (wyjście) = 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'

Licząc shebang jako 2 bajty, po jednym dla każdej opcji. Po pierwsze, każde z ośmiu poleceń jest tłumaczone na zakres p-w, jednocześnie usuwając wszystkie pozostałe znaki. Łańcuch ten jest następnie kodowany i uruchamiany przy użyciu minimalnego dekodera / interpretera. Kilka rzeczy zostało zoptymalizowanych: łańcuch ><oczywiście nic nie robi, a pętla for, która następuje bezpośrednio po innej, może zostać całkowicie usunięta, ponieważ nigdy nie zostanie wprowadzona.

Dane wyjściowe dla programu testowego:

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

Przykładowy przebieg:

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

Perl - 232 (źródło) + 21 (wyjście) = 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\"")

Ten opiera się na spostrzeżeniu FIQ , że jeśli oryginalny program nie zawiera instrukcji wejściowej, wynik będzie statyczny, a zatem może zostać zredukowany do pojedynczej printinstrukcji. Jeśli ci się podoba, pamiętaj, aby dać jego odpowiedź +1.

Więc co możemy zrobić, to potokować stdoutdo zmiennej, evalkod, który otrzymalibyśmy, i zawinąć wynik w print.

... to jednak nie zawsze zadziała. Ilekroć kod do przetłumaczenia spowodowałby nieskończoną pętlę (np. +[.]), Z oczywistych powodów nie można tego zredukować do pojedynczej printinstrukcji. Zamiast tego uruchamiamy evalproces potomny z krótkim limitem czasu, a jeśli nie zakończy się on w tym czasie, wysyłamy przetłumaczony program jak poprzednio.

Zorganizowany i skomentowany:

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

Dane wyjściowe dla przykładowego programu:

print"Hello\ world\!"

Dane wyjściowe dla ,[.]:

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

Wyjście dla +[.](po 9 sekundach):

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

1
To jest niesamowite! Mózg boli :)
— Timwi

Myślę, że wv.*?(?=w)jest źle. Myślę, że usunie tylko kod do następnego ], ale potrzebujesz go, aby znaleźć pasujące ] ; musisz zadbać o zagnieżdżanie ...
— Timwi

@Timwi Naprawiono, ignorując zagnieżdżone przypadki wv[^v]*(?=w), które są znacznie krótsze niż alternatywa.
— primo

14

Brainfuck, 5 + 540 = 545 bajtów

5 bajtów kodu, 540 z danych wyjściowych danego pliku testowego (zakładając, że otrzymałem liczbę bezpośrednio z mojej pasty tego kodu).

,[.,]

Zakładając, że EOF wynosi 0.


@primo, ponieważ nie resetuje się przed odczytem interpretera, który nie zmienia wartości w EOF, sprawi, że ten program będzie nieskończoną pętlą dla wszystkich danych wejściowych większych niż 0 bajtów.
— Sylwester

Nie mogę się zastanawiać, jakie oprogramowanie jest używane do uruchamiania tych rzeczy? xD
— Teun Pronk

@TeunPronk Istnieje tłumacz pieprzony mózg o nazwie bfi ( github.com/susam/bfi ). Wystarczy go skompilować i zainstalować, a następnie uruchomić w następujący sposób: bfi input.bfgdzie input.bfnależy interpretować plik pieprzony mózg.
— Braden Best

5

PHP, 553 + 27 = 580 bajtów

(Usunięto 553 bajtów ze wszystkimi białymi spacjami, tj. Znakami nowej linii i spacjami)

Źle podchodzę do gry w golfa w PHP, więc to podejście można mocno zoptymalizować. Chciałem przede wszystkim pokazać swoje podejście do rozwiązania w czymś innym niż 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);

Raportowanie błędów musi być wyłączone, w przeciwnym razie PHP cię nienawidzi. Sposób użycia: wyrzuć to jako stronę i uruchom za pomocą script.php? C = CODE (jeśli wynikowy skrypt wymaga danych wejściowych, uruchom go jako out.php? I = INPUT). Pamiętaj, aby URL uratować wejście!

To, co to robi, jest w zasadzie takie - jeśli skrypt BF zawiera „,”, to właściwie osadza się jako wynikowy skrypt z dołączonym $ b = 1; na górze. Jeśli NIE zawiera „,”, optymalizuje go do „echo <wyjście BF>”. Dogodnie skrypt testowy w PO NIE wymaga żadnych danych wejściowych. Addlasheshes () służy tylko do ucieczki 'i \.


4

C ++, 695 + 510 = 1205 bajtów

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

Wynik:

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

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

Wynik:

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

1

io

659 + 553 = 1212

Rzeczy takie jak File standardInput readBufferOfLength(1)zabijanie liczby bajtów, ale nie mogę tego obejść. Nie robiłem optymalizacji pod kątem powtarzających się symboli lub braku danych wejściowych w programie BF, ale będę nadal nad tym pracował, również nad tym, który korzysta z możliwości metaprogramowania 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))

Testowanie

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

Wydajność

Hello world!
659  +  553  = 1212

1

Brainfuck , 109 + 407 = 516

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

Wypróbuj online!

Usuwa tylko operacje inne niż BF i nie analizuje innych optymalizacji.


0

Lua - 328 + 2256 = 2584

(Och, właśnie zdałem sobie sprawę, że musisz również dodać długość wyniku, słaby wynik, wygląda na to)

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

Zrobione z tym odpowiedź kopalni.


0

Lua - 319 + 21 = 340

Jest to prawdopodobnie najkrótszy kod ze wszystkich, ale nie przyjmuje danych wejściowych, więc jest trochę oszustwo. Wpadłem na pomysł innej wersji z wejściem, patrz koniec tego komentarza.

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

Ta wersja ma udowodnić, że lua może zrobić lepiej niż 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;"}))()')

Obie wersje dodają 30000 bajtów danych. Moja druga wersja opiera się na danych wejściowych / wyjściowych: wszystko po „.” lub „,” zostaną usunięte. Moja druga wersja nie zezwala na nieskończone pętle ([.,], [] Itd.)

Moim pomysłem jest uzyskanie:

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

Z twojego wkładu, z dodatkowym „, +”.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.