Напишіть перекладача на голову


18

У будь-якій мові програмування чи скриптів x напишіть програму, яка бере дійсний вихідний код brainfuck від stdin та output, щоб stdout, вихідний код програми, написаний мовою x , який виводив би те саме, що і програма 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
Ви можете додати пункт про те, що мова, якою ви не користуєтеся, також не є ебаною;)
Josh

@Josh добре, якщо комусь вдалося написати коротку програму, яка видаляє непотрібні непотрібні коди, чому б не дати їм це зробити?
користувач12205

2
Ну просто тому, що тривіальне рішення виведення джерела без змін буде мати дійсно низький бал у будь-якому випадку для мозкового ебання. Я буду здивований, якщо інша мова може це перемогти.
Тім Сегуїн

@Tim Seguine Я міг би змінити питання, але чи не буде це несправедливо стосовно тих, хто вже надав відповідь? І якщо я зміню питання, я думаю про те, щоб змінити підрахунок балів, зробити це byte count of source + (byte count of output)^2, чи спонукає людей більше зосередитися на спрощенні результатів?
користувач12205

Як правило, зміна такого питання після того, як воно вже отримало відповідь, нахмуриться. Я тільки вказував причину, чому я вважаю, що Джош мав рацію. Добре розмістити такі речі спочатку в пісочниці, щоб ви могли вирішити потенційні проблеми, будучи справедливими для всіх.
Тім Сегуїн

Відповіді:


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'

Порахувавши шебанг як 2 байти, по одному на кожен варіант. По-перше, кожна з восьми команд переводиться на діапазон 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код, який ми отримаємо, і обернути результат в a 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
Це дивно! Мозок болить :)
Тімві

Я думаю, що wv.*?(?=w)це неправильно. Я думаю, що він видалить код лише до наступного ], але вам він потрібен для пошуку відповідності ] ; вам потрібно подбати про гніздування ...
Timwi

@Timwi Виправлено, ігноруючи вкладені випадки wv[^v]*(?=w), що значно коротше альтернативи.
примо

14

Brainfuck, 5 + 540 = 545 байт

5 байтів коду, 540 від виходу даного тестового файлу (якщо припустити, що кількість рахунків прямо з моєї пасти цього коду).

,[.,]

Припустимо, що EOF дорівнює 0.


@primo, оскільки він не скидається перед читанням інтерпретатора, який не змінює значення на EOF, зробить цю програму нескінченним циклом для всіх вхідних даних більше 0 байт.
Сильвестр

Я не можу допомогти задатися питанням, яке програмне забезпечення використовується для запуску цього матеріалу? xD
Teun Pronk

@TeunPronk Є інтерпретатор, який називається мозгbfi (" github.com/susam/bfi" ). Просто компілюйте та встановіть його та запустіть так: bfi input.bfде input.bfслід інтерпретувати файл fufuck.
Бреден Кращий

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; на вершині. Якщо він НЕ містить ",", він оптимізує його до "відлуння" <вихід BF> '". Зручно, що тестовий сценарій в ОП НЕ вимагає введення. Додавання () якраз є для втечі 'та \.


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

Пітон - 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

іо

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

Ця версія - довести, що Луа може зробити краще, ніж 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)

З вашого вводу, із додатковим ", +".

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.