Интерпретировать мозг ***


113

Напишите самую короткую программу на вашем любимом языке, чтобы интерпретировать программу « бред ». Программа читается из файла. Вход и выход являются стандартным входом и стандартным выходом.

  1. Размер ячейки: 8 бит без знака. Переполнение не определено.
  2. Размер массива: 30000 байт (не обведено)
  3. Плохие команды не являются частью ввода
  4. Комментарии начинаются с символа # и продолжаются до конца строки комментировать все не+-.,[]<>
  5. нет символа EOF

Очень хороший тест можно найти здесь . Он читает число, а затем печатает простые числа до этого числа. Чтобы предотвратить гниение ссылок, вот копия кода:

compute prime numbers
to use type the max number then push Alt 1 0
===================================================================
======================== OUTPUT STRING ============================
===================================================================
>++++++++[<++++++++>-]<++++++++++++++++.[-]
>++++++++++[<++++++++++>-]<++++++++++++++.[-]
>++++++++++[<++++++++++>-]<+++++.[-]
>++++++++++[<++++++++++>-]<+++++++++.[-]
>++++++++++[<++++++++++>-]<+.[-]
>++++++++++[<++++++++++>-]<+++++++++++++++.[-]
>+++++[<+++++>-]<+++++++.[-]
>++++++++++[<++++++++++>-]<+++++++++++++++++.[-]
>++++++++++[<++++++++++>-]<++++++++++++.[-]
>+++++[<+++++>-]<+++++++.[-]
>++++++++++[<++++++++++>-]<++++++++++++++++.[-]
>++++++++++[<++++++++++>-]<+++++++++++.[-]
>+++++++[<+++++++>-]<+++++++++.[-]
>+++++[<+++++>-]<+++++++.[-]

===================================================================
======================== INPUT NUMBER  ============================
===================================================================
+                          cont=1
[
 -                         cont=0
 >,
 ======SUB10======
 ----------

 [                         not 10
  <+>                      cont=1
  =====SUB38======
  ----------
  ----------
  ----------
  --------

  >
  =====MUL10=======
  [>+>+<<-]>>[<<+>>-]<     dup

  >>>+++++++++
  [
   <<<
   [>+>+<<-]>>[<<+>>-]<    dup
   [<<+>>-]
   >>-
  ]
  <<<[-]<
  ======RMOVE1======
  <
  [>+<-]
 ]
 <
]
>>[<<+>>-]<<

===================================================================
======================= PROCESS NUMBER  ===========================
===================================================================

==== ==== ==== ====
numd numu teid teiu
==== ==== ==== ====

>+<-
[
 >+
 ======DUP======
 [>+>+<<-]>>[<<+>>-]<

 >+<--

 >>>>>>>>+<<<<<<<<   isprime=1

 [
  >+

  <-

  =====DUP3=====
  <[>>>+>+<<<<-]>>>>[<<<<+>>>>-]<<<

  =====DUP2=====
  >[>>+>+<<<-]>>>[<<<+>>>-]<<< <


  >>>


  ====DIVIDES=======
  [>+>+<<-]>>[<<+>>-]<   DUP i=div

  <<
  [
    >>>>>+               bool=1
    <<<
    [>+>+<<-]>>[<<+>>-]< DUP
    [>>[-]<<-]           IF i THEN bool=0
    >>
    [                    IF i=0
      <<<<
      [>+>+<<-]>>[<<+>>-]< i=div
      >>>
      -                  bool=0
    ]
    <<<
    -                    DEC i
    <<
    -
  ]

  +>>[<<[-]>>-]<<          
  >[-]<                  CLR div
  =====END DIVIDES====


  [>>>>>>[-]<<<<<<-]     if divides then isprime=0


  <<

  >>[-]>[-]<<<
 ]

 >>>>>>>>
 [
  -
  <<<<<<<[-]<<

  [>>+>+<<<-]>>>[<<<+>>>-]<<<

  >>




  ===================================================================
  ======================== OUTPUT NUMBER  ===========================
  ===================================================================
  [>+<-]>

  [
   ======DUP======
   [>+>+<<-]>>[<<+>>-]<


   ======MOD10====
   >+++++++++<
   [
    >>>+<<              bool= 1
    [>+>[-]<<-]         bool= ten==0
    >[<+>-]             ten = tmp
    >[<<++++++++++>>-]  if ten=0 ten=10
    <<-                 dec ten     
    <-                  dec num
   ]
   +++++++++            num=9
   >[<->-]<             dec num by ten

   =======RROT======
      [>+<-]
   <  [>+<-]
   <  [>+<-]
   >>>[<<<+>>>-]
   <

   =======DIV10========
   >+++++++++<
   [
    >>>+<<                bool= 1
    [>+>[-]<<-]           bool= ten==0
    >[<+>-]               ten = tmp
    >[<<++++++++++>>>+<-] if ten=0 ten=10  inc div
    <<-                   dec ten     
    <-                    dec num
   ]
   >>>>[<<<<+>>>>-]<<<<   copy div to num
   >[-]<                  clear ten

   =======INC1=========
   <+>
  ]

  <
  [
   =======MOVER=========
   [>+<-]

   =======ADD48========
   +++++++[<+++++++>-]<->

   =======PUTC=======
   <.[-]>

   ======MOVEL2========
   >[<<+>>-]<

   <-
  ]

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

  ===================================================================
  =========================== END FOR ===============================
  ===================================================================


  >>>>>>>
 ]
 <<<<<<<<



 >[-]<
  [-]
 <<-
]

======LF========

++++++++++.[-]
@

Пример выполнения:

$ python2 bf.py PRIME.BF 
Primes up to: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 

5
Вы должны уточнить примерно 1) размер памяти 2)
обведена ли

3
Интересно, должно ли быть две категории: те программы, которые используют eval (или shell для компиляции) - и те, которые этого не делают.
MtnViewMark

34
Я хотел бы видеть, что кто-то ответит на это в мозгах.
Ханнеш

3
Что означает «нет символа EOF»? Что значение ячейки остается неизменным при попытке ,EOF? Или что мы сами должны выбрать значение, когда примеряем ,EOF? Или EOF вообще неопределенное поведение?
Мартин Эндер

3
Точно так же, что должно произойти, когда кто-то пытается оставить ячейки 30k в любую сторону? Должна ли головка ленты оставаться на месте или это неопределенное поведение?
Мартин Эндер

Ответы:


46

Perl, 120 138

%c=qw(> $p++ < $p-- + D++ - D-- [ while(D){ ] } . print+chrD , D=ord(getc));
$/=$,;$_=<>;s/./$c{$&};/g;s[D]'$b[$p]'g;eval

Это без проблем работает hello.bf и primes.bf:

$ perl bf.pl hello.bf
Hello World!
$ perl bf.pl prime.bf
Primes up to: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97

Инициализация: таблица перевода кода операции в Perl хранится в %c. Читаемая форма выглядит так:

%c=(
  '>' => '$p++',
  '<' => '$p--',
  '+' => '$b[$p]++',
  '-' => '$b[$p]--',
  '[' => 'while($b[$p]){',
  ']' => '}',
  '.' => 'print chr$b[$p]',
  ',' => '$b[$p]=ord(getc)',
);

Шаг 1: Зафиксировать входные данные программы $_и преобразовать их в код Perl, используя таблицу перевода. Комментарии автоматически удаляются (заменяются undef) на этом этапе.

Шаг 2: Распакуйте все $b[$p]вхождения

Шаг 3: Запустите программу, используя eval.


Просто используйте qwсинтаксис Perl для %cпрямого определения - хорошо на 7 символов меньше (вы должны будете сказать, print+chr$b[$p]и ord(getc)хотя)
моб

Я считаю 18 спасенных ... спасибо! (обновление через минуту)
JB

1
@olivecoder О чем ты вообще говоришь?
JB

Таблица% c объявлена ​​и определена в первой строке; его персонажи прекрасно учтены.
JB

@JB эй, я случайно нажал на голосование по твоему ответу, и он заблокирован, можешь отредактировать это, чтобы я мог отменить голосование?
Циклогексанол.

67

Python (не eval), 317 байт

from sys import*
def f(u,c,k):
 while(c[1]>=k)*u:
  j,u='[]<>+-,.'.find(u[0]),u[1:];b=(j>=0)*(1-j%2*2);c[1]+=b*(j<2)
  while b*c[c[0]]and j<1:f(u,c,k+1);c[1]+=1
  b*=c[1]==k;c[[0,c[0],2][j/2-1]]+=b
  if(j==6)*b:c[c[0]]=ord(stdin.read(1))
  if(j>6)*b:stdout.write(chr(c[c[0]]))
f(open(argv[1]).read(),[-1]+[0]*30003,0)

70
+1 заf(u,c,k)
Джоэл Корнетт

9
Это один прекрасный кусок шума, сэр
сумасшедший

-1 байт, если заменить while b*c[c[0]]and j<1наwhile b*c[c[0]]*(j<1)
Даниил Тутубалин

50

16 бит 8086 машинный код: 168 байт

Вот версия в кодировке base64 , преобразуйте и сохраните как «bf.com» и запустите из командной строки Windows: «bf progname»

gMYQUoDGEFKzgI1XAgIfiEcBtD3NIR8HcmOL2LQ/i88z0s0hcleL2DPA86sz/zP2/sU783NHrL0I
AGgyAU14DTqGmAF194qOoAH/4UfDJv4Fwyb+DcO0AiaKFc0hw7QBzSGqT8MmODV1+jPtO/NzDaw8
W3UBRTxddfJNee/DJjg1dPoz7U509YpE/zxddQFFPFt18U157sM+PCstLixbXUxjTlJWXmV+

РЕДАКТИРОВАТЬ

Вот некоторый ассемблер (стиль A86) для создания исполняемого файла (мне пришлось перепроектировать его, так как я потерял исходный код!)

    add dh,10h                              
    push dx                                 
    add dh,10h                              
    push dx                                 
    mov bl,80h                              
    lea dx,[bx+2]                         
    add bl,[bx]                            
    mov [bx+1],al                         
    mov ah,3dh                              
    int 21h                                 
    pop ds                                 
    pop es                                 
    jb ret                               
    mov bx,ax                              
    mov ah,3fh                              
    mov cx,di                              
    xor dx,dx                              
    int 21h                                 
    jb ret                               
    mov bx,ax                              
    xor ax,ax                              
    repz stosw                                     
    xor di,di                              
    xor si,si                              
    inc ch                                 
program_loop:
    cmp si,bx                              
    jnb ret                               
    lodsb                                    
    mov bp,8                            
    push program_loop
symbol_search:                       
    dec bp                                 
    js ret
    cmp al,[bp+symbols]
    jnz symbol_search
    mov cl,[bp+instructions]
    jmp cx                                 
forward:
    inc di                                 
    ret                                    
increment:
    inc b es:[di]                      
    ret                                    
decrement:
    dec b es:[di]                      
    ret                                    
output:
    mov ah,2                              
    mov dl,es:[di]                            
    int 21h                                 
    ret                                    
input:
    mov ah,1                              
    int 21h                                 
    stosb                                    
backward:
    dec di                                 
    ret                                    
jumpforwardifzero:
    cmp es:[di],dh                            
    jnz ret                               
    xor bp,bp
l1: cmp si,bx                              
    jnb ret
    lodsb                                    
    cmp al,'['                              
    jnz l2
    inc bp
l2: cmp al,']'                              
    jnz l1
    dec bp                                 
    jns l1
    ret                                    
jumpbackwardifnotzero:
    cmp es:[di],dh                            
    jz  ret
    xor bp,bp
l3: dec si                                 
    jz  ret
    mov al,[si-1]                         
    cmp al,']'
    jnz l4
    inc bp  
l4: cmp al,'['                              
    jnz l3
    dec bp                                 
    jns l3
    ret                                    
symbols:
    db '><+-.,[]'
instructions:
    db forward and 255
    db backward and 255
    db increment and 255
    db decrement and 255
    db output and 255
    db input and 255
    db jumpforwardifzero and 255
    db jumpbackwardifnotzero and 255

Я добавил исходную версию программы. Я только что заметил, что не-bf символы вызывают выход из программы, а не игнорируются. Это легко исправить, и я оставлю это в качестве упражнения для людей, которые делают это сами.
Skizz

Я помню, что получил Linux ELF версии 166 байт, 10 лет назад, здесь muppetlabs.com/~breadbox/software/tiny
Эммануэль

39

брейкфак , 843 691 байт

Редактировать: решил вернуться к этому и нашел удивительное количество способов игры в гольф от байтов

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

Это принимает ввод в форме, code!inputгде !inputнеобязательно. Он также моделирует отрицательные ячейки без использования самих отрицательных ячеек и может хранить их до (30000-(length of code+6))/2ячеек.

Попробуйте онлайн!


Просто чтобы убедиться, что я понял это правильно, если бы я запустил эту программу с этой программой, я мог бы вложить ее в 5 уровней и по-прежнему обрабатывать вводы кода длиной 262.
Draco18s

@ Draco18s Я подозреваю, что вы до этого исчерпали 30000 ячеек, так как размер каждого вложенного интерпретатора увеличивается в геометрической прогрессии. Я думаю, что вы получите 2, может быть, 3 уровня в глубину
Джо Кинг

Даже 3 глубоких было бы смешно глупо.
Draco18s

27

Ruby 1.8.7, 188 185 149 147 символов

eval"a=[i=0]*3e4;"+$<.bytes.map{|b|{?.,"putc a[i]",?,,"a[i]=getc",?[,"while a[i]>0",?],"end",?<,"i-=1",?>,"i+=1",?+,"a[i]+=1",?-,"a[i]-=1"}[b]}*";"

Несколько читаемая версия:

code = "a = [0] * 3e4; i = 0;"
more_code ARGF.bytes.map {|b|
  replacements = {
    ?. => "putc a[i]",
    ?, => "a[i] = getc",
    ?[ => "while a[i] > 0 do",
    ?] => "end",
    ?< => "i -= 1",
    ?> => "i += 1",
    ?+ =>"a[i]+=1",
    ?- =>"a[i]-=1"
  }
  replacements[b]
}.join(";")
eval code+more_code

Как вы видите, я бесстыдно украл вашу идею о переводе на основной язык, а затем использовал eval для его запуска.


Вы можете сбрить байт байт по сравнению с нуля , >0а не проверки равенства: !=0. В спецификациях указано unsigned, а переполнение не определено.
анонимный трус

3e4будет также работать в противоположность30000
анонимный трус

@ Чарли: Спасибо. Хотя, честно говоря, он не сказал "без знака", когда я писал код. Честно говоря, я не знал, что ты можешь написать 3e4. Это очень хороший момент и полезно знать.
sepp2k

File.read($*.pop).bytes-> $<.bytesдолжно работать тоже
Арно Ле Блан

1
Ruby 1.8.7 имеет еще более короткий синтаксис для построения буквального хэша:, {?a,"foo"}что эквивалентно {?a=>"foo"}. И здесь тестирование показывает , что вы на самом деле можно заменить File.read($*.pop).bytesс $<без каких - либо проблем. Также встраивание всего в что-то вроде eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";"сокращает решение еще на несколько символов.
Вентеро

26

Двоичное лямбда-исчисление 112

Программа показанная в шестнадцатеричном дампе ниже

00000000  44 51 a1 01 84 55 d5 02  b7 70 30 22 ff 32 f0 00  |DQ...U...p0".2..|
00000010  bf f9 85 7f 5e e1 6f 95  7f 7d ee c0 e5 54 68 00  |....^.o..}...Th.|
00000020  58 55 fd fb e0 45 57 fd  eb fb f0 b6 f0 2f d6 07  |XU...EW....../..|
00000030  e1 6f 73 d7 f1 14 bc c0  0b ff 2e 1f a1 6f 66 17  |.os..........of.|
00000040  e8 5b ef 2f cf ff 13 ff  e1 ca 34 20 0a c8 d0 0b  |.[./......4 ....|
00000050  99 ee 1f e5 ff 7f 5a 6a  1f ff 0f ff 87 9d 04 d0  |......Zj........|
00000060  ab 00 05 db 23 40 b7 3b  28 cc c0 b0 6c 0e 74 10  |....#@.;(...l.t.|
00000070

ожидает, что его входные данные состоят из программы Brainfuck (для различения используются только биты 0,1,4, -. + <>] [), за которыми следует a], а затем ввод для программы Brainfuck.

Сохраните вышеуказанный шестнадцатеричный дамп с помощью xxd -r> bf.Blc

Получите переводчик blc из https://tromp.github.io/cl/cl.html

cc -O2 -DM=0x100000 -m32 -std=c99 uni.c -o uni
echo -n "++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.]" > hw.bf
cat bf.Blc hw.bf | ./uni

Привет, мир!


1
Почему это вообще существует? По-видимому, он даже существует в области исследований . Оо
Исия Медоуз

Так что это не будет работать с прокомментированными программами brainfuck?
kamoroso94

Нет, не без предварительного удаления комментариев.
Джон Тромп

18

Сетчатка 0.8.2 , 386 391 386 байт

Код содержит непечатаемые 0x00символы NUL ( ). Это также еще не супер гольф, потому что он уже очень медленный, и если я играю в гольф больше, я не знаю, сколько времени потребуется, чтобы закончить. Появляется тайм-аут по первичной выборке.

Могут быть ошибки в онлайн-переводчике или в моей программе (новые строки не отображаются в выводе?).

Принимает участие как <code>│<input>. Нет, это не труба ( |). Это персонаж Юникода U+2502. Код также использует символы Unicode ÿ▶◀├║. Символы Unicode используются для поддержки ввода всех символов ASCII. Следовательно, эти символы должны быть отделены от кода не-ASCII-символом.

Попробуйте онлайн

s`^.*
▶$0├║▶
s{`(▶>.*║.*)▶(.)(.?)
$1$2▶$3
▶$
▶
║▶
║▶
(▶<.*║.*)(.)▶
$1▶$2
T`ÿ-`o`(?<=▶\+.*║.*▶).
^\+

T`-ÿ`ÿo`(?<=▶-.*║.*▶).
^-

(▶\..*├.*)(║.*▶)(.)
$1$3$2$3
(▶,.*│)(.?)(.*├.*▶).
$1$3$2
▶\[(.*║.*▶)
[▶▶${1}
{`(▶▶+)([^[\]]*)\[
$2[$1▶
}`▶(▶+)([^[\]]*)\]
$2]$1
r`([[\]]*)▶\](.*║.*▶[^])
$1◀◀]$2
r{`\[([^[\]]*)(◀+)◀
$2[$1
}`\]([^[\]]*)(◀◀+)
$2◀]$1
◀
▶
}`▶([^│])(.*║)
$1▶$2
s\`.*├|║.*

Обратите внимание, что там есть завершающий перевод строки.

Краткое объяснение:

Нули 0x00используются для ленты, которая бесконечна. Первая замена устанавливает интерпретатор в форме ▶<code>│<input>├<output>║▶<tape>, где первый - указатель на код, а второй - указатель на ленту.

ÿis 0xFF(255), который используется для транслитерации (используется для реализации +и -), чтобы обернуть ячейки обратно в ноль.

используется только для удобства чтения (если программа остановлена ​​посередине или вы хотите увидеть ее выполнение в середине). В противном случае вы не сможете определить, в какую сторону двигался указатель.

Код комментирования:

s`^.*                       # Initialize
▶$0├║▶
s{`(▶>.*║.*)▶(.)(.?)        # >
$1$2▶$3
▶$
▶
║▶                          # <
║▶
(▶<.*║.*)(.)▶
$1▶$2
T`ÿ-`o`(?<=▶\+.*║.*▶).      # +
^\+

T`-ÿ`ÿo`(?<=▶-.*║.*▶).      # -
^-

(▶\..*├.*)(║.*▶)(.)         # .
$1$3$2$3
(▶,.*│)(.?)(.*├.*▶).        # ,
$1$3$2
▶\[(.*║.*▶)                 # [
[▶▶${1}
{`(▶▶+)([^[\]]*)\[
$2[$1▶
}`▶(▶+)([^[\]]*)\]
$2]$1
r`([[\]]*)▶\](.*║.*▶[^])    # ]
$1◀◀]$2
r{`\[([^[\]]*)(◀+)◀
$2[$1
}`\]([^[\]]*)(◀◀+)
$2◀]$1
◀
▶
}`▶([^│])(.*║)              # next instruction
$1▶$2
s\`.*├|║.*                  # print output

Нажмите здесь, чтобы получить код с нулями вместо нулевых байтов. Любые вхождения $0не должны заменяться нулями.

Редактировать : теперь поддерживает пустой ввод и подавляет завершающий перевод строки.

Бесконечный вывод теперь поддерживается. (403 байта)


Я как бы хотел, чтобы я поместил <code>и <tape>рядом друг с другом (хотя это было бы больше символов), чтобы переход к интерпретатору SMBF был бы легче, если бы я когда-нибудь решил это сделать.
mbomb007

14

TI-BASIC, 264 байта

Из-за ограничений в TI-BASIC, это на самом деле не подходит для этой задачи, поскольку нарушает правило 2; ОЗУ калькуляторов очень ограничено, и выполнение чего-то вроде 30000->dim(L1(я использую L1 для стека / массива) заставит его выбросить ERR:MEMORY. Таким образом, стек / массив начинается с размера 1 и увеличивается, если указатель указывает на элемент после его конца. Это также нарушает правило 3, потому что оно уже нарушает правило 2, поэтому я могу не беспокоиться о пределе размера ячейки.

Кстати, возможно, все еще можно сыграть в гольф ... Я сделал одно или два изменения с этой целью с момента первой отправки, но если приведенная ниже версия не работает, вернитесь к редактированию с 6 мая 15 года и используйте это код вместо Кроме того, поскольку в TI-BASIC ASCII действительно нет, он принимает числа любого размера (и все, что возвращает число, например, переменную или выражение) в качестве входных данных и выводит числа по очереди.

Используйте SourceCoder, чтобы встроить его в файл .8xp, затем отправьте его на свой калькулятор с помощью TI-Connect или TILP или чего-то еще, и запустите его, включив вашу программу brainfuck в двойные кавычки, за которой следует двоеточие и все, что вы назвали программой TI-BASIC. Например, если вы назвали его BrainF, вы бы запустить программу , как это: "brainfuck goes here":prgmBRAINF. Если у вас есть раковина на вашем известково , который перехватывает другие команды , когда он обнаруживает prgmмаркер, однако, сделать это: "brainfuck goes here" -> press ENTER -> prgmBRAINF.

seq(inString("<>-+.,[]",sub(Ans,S,1)),S,1,length(Ans->L2
cumSum((Ans=7)-(Ans=8->L3
seq(Ans(X),X,dim(Ans),1,~1->L4
1->P:DelVar L11->dim(L1 //this is the same as DelVar L1:1->dim(L1 as DelVar does not require a colon or newline after its argument
For(S,1,dim(L2
L2(S->T
P-(T=1)+(T=2->P
dim(L1
Ans+(P-Ans)(P>Ans->dim(L1
L1(P)-(T=3)+(T=4->L1(P
If T=5
Disp Ans
If T=6:Then
Input V
V->L1(P
End
If T=7 and not(L1(P
S+2+sum(not(cumSum(L3(S)-1=seq(L3(X),X,S+1,dim(L3->S
1-S+dim(L3
If T=8 and L1(P
S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S
End

Если у вас нет способа подключить калькулятор к компьютеру, и вы хотите вместо этого напечатать его на калькуляторе (я не могу представить, почему вы хотите этого, но я отвлекся), обратите внимание, что ->это STO>кнопка над ON key, ~является отрицательным символом рядом с ENTER и заменяет все экземпляры L<number>на соответствующий токен списка, найденный на2ND -> <number on keypad>

Благодаря Томаса- кВА (по крайней мере, я думаю , что его стек имя пользователя) помог мне оптимизировать это, особенно с [и ]инструкциями.


1
Тебе нужны парни вокруг Ans+S?
Захари

@ Zacharý Хороший улов, нет. Должно быть, я не был уверен в том, как работает PEMDAS или что-то в этом роде ... Я воздержусь от редактирования, однако, потому что это было так долго, что определенно не стоит поднимать этот пост на первый план и потому, что двухбайтовый сокращение не даст ответу какое-либо преимущество перед другими, лол.
М.И. Райт

1
Я помню, как 2-3 года назад, когда я использовал эту программу для интерпретации Brainf *** на моем калькуляторе. И это очень сложный вопрос, думаю, он должен быть на вершине, если честно.
Захари

1
На самом деле, я думаю, что целая строка может быть S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. ( a-a=0). И, эй, не беспокойтесь о том, что вы забыли ОДИН порядок операций здесь, я видел множество людей, которые забыли порядок операций для %(мода) в вызове.
Захари

1
О черт, да. Хорошо, это дает по крайней мере 10 байтов, поскольку if может быть также сделана однострочной, плюс некоторые другие вещи ... также можно редактировать. Ты заставил меня впервые за год проверить свой калькулятор, чтобы проверить это, хаха
М.И. Райт,

13

Питон 275 248 255

Я решил попробовать.

import sys
i=0
b=[0]*30000
t=''
for e in open(sys.argv[1]).read():
 t+=' '*i+['i+=1','i-=1','b[i]+=1','b[i]-=1','sys.stdout.write(chr(b[i]))','b[i]=ord(sys.stdin.read(1))','while b[i]:','pass','']['><+-.,['.find(e)]+'\n'
 i+=(92-ord(e))*(e in'][')
exec t 

12
Neat, вы генерируете исходный код Python, используя brainfuck.

1
Вы можете удалить 1 символ, «импортировать sys как s» и заменить «sys» на «s» в остальных
ВЫ

Обратите внимание, что это на самом деле 247 символов. (Видите грязное пространство после exec t?). Если вы используете наконечник S.Mark , а также делаете весь forцикл в одну строку, вы можете уменьшить его до 243 символов.
Олег Припин

Это терпит неудачу на любом входе, содержащем [], допустимую хотя бы тривиальную программу bf. Я предложил редактирование, которое исправляет это, но увеличивает количество символов. Чтобы еще больше уменьшить количество символов, вы можете from sys import *и использовать 'i+=1,...'.split(',')вместо ['i+=1',...].
Boothby

7
Я бы +1, но многие улучшения были предложены и не реализованы.
mbomb007

12

Haskell, 457 413 символов

import IO
import System
z=return
'>'#(c,(l,d:r))=z(d,(c:l,r))
'<'#(d,(c:l,r))=z(c,(l,d:r))
'+'#(c,m)=z(succ c,m)
'-'#(c,m)=z(pred c,m)
'.'#t@(c,_)=putChar c>>hFlush stdout>>z t
','#(_,m)=getChar>>=(\c->z(c,m))
_#t=z t
_%t@('\0',_)=z t
i%t=i t>>=(i%)
b('[':r)=k$b r
b(']':r)=(z,r)
b(c:r)=f(c#)$b r
b[]=(z,[])
f j(i,r)=(\t->j t>>=i,r)
k(i,r)=f(i%)$b r
main=getArgs>>=readFile.head>>=($('\0',("",repeat '\0'))).fst.b

Этот код «компилирует» программу BF в IOдействие в форме, State -> IO Stateв которой состояние представляет собой застежку-молнию на бесконечной строке.

Печально, что мне пришлось потратить 29 символов, чтобы отключить буферизацию. Без них это работает, но вы не видите подсказки, прежде чем вводить ввод. Сам компилятор ( b, fи k), всего 99 символов, среда выполнения ( #а %) является 216. водитель ж / исходное состояние другого 32.

>ghc -O3 --make BF.hs 
[1 of 1] Compiling Main             ( BF.hs, BF.o )
Linking BF ...

>./BF HELLO.BF 
Hello World!

>./BF PRIME.BF 
Primes up to: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97 

обновление 2011-02-15: Включены предложения JB, сделано небольшое переименование и исправленыmain


1
Вы должны быть в состоянии получить буферизацию от just IO, а аргументы от just System(-19). Проблема с буферизацией также беспокоит меня, так как спецификация на самом деле не упоминает об этом, а ответ с наибольшим количеством голосов даже не выполняет ввод-вывод. Если вы должны сохранить его, вероятно, hFlushпосле каждой записи оно будет короче, чем изменение режима глобальной буферизации (-34 + 15).
JB

11

Конвейер, 953

Это может быть самый красивый код, который вы когда-либо видели:

0

:I\1\@p
>#====)
^#====<
PP0
P<=======================<
00t:)01t1  a:P:P:P:P:P:P:^
>===========">">2>">2>">"^
^           +^-^5^ ^5^]^.^
^           "^"^*^"^*^"^"^
^           -^-^6^-^6^-^-^
^           #^#^*^#^*^#^#^
^           P P -^P )^P P
^           P P #^P )^P P
^t1\)t0:))t01   P   -^  1
^===========<   P   #^  0
^  t1\(t0:))t01     P   t
^=============<     P   )
^         t11(t01   0 0 )
^===============<. t P 10
^                 FT#T#=<
^=================< P 
^             t11)t01 
^===================< 10t))0tP00t:(01t(1a:P:
^                     >=====#=>==========">"
^                             ^          ]^[
^                           P ^          "^"
^===========================<=^#=====<   -^-
                            ^==<     ^ PP#^#=
                                     ^===PTPT<
                                     ^  )P P
                                     ^=<=< (
                                       ^===<

8
Не могли бы вы добавить объяснение и ссылку на реализацию? Я хочу понять красоту. ;)
DLosc

1
Ну, я сейчас его разрабатываю, есть компилятор и очень плохое объяснение на github.com/loovjo/Conveyor . Источник довольно читабелен, если вы хотите понять это.
Loovjo

9

C 284 362 (из файла)

#include <stdio.h>
char b[30000],z[9999],*p=b,c,*a,i;f(char*r,int s){while(c=*a++){if(!s){(c-62)?(c-60)?(c-43)?(c-45)?(c-46)?(c-44)?0:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;if(c==91)f(a,!*p);else if(c==93){if(!*p)return;else a=r;}}else{if(c==93){--s;if(!*p&&!s)return;}else if(c==91){s++;}}}}main(int c,char**v){fread(z,1,9999,fopen(*++v,"r"));a=z;f(0,0);}

Штрихи:

Простые числа до: 100
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
Нажмите любую клавишу для продолжения . , ,

Скомпилировано и успешно запущено VS2008

Исходное решение не смогло распознать циклы, которые изначально были установлены на ноль. Еще есть место для гольфа. Но, наконец, решает программу Prime Number.

Ungolfed:

#include <stdio.h>
char b[30000],z[9999],*p=b,c,*a,i;
f(char*r,int s)
{
    while(c=*a++)
    {   
        if(!s)
        {
            (c-62)?(c-60)?(c-43)?(c-45)?(c-46)?(c-44)?0:(*p=getchar()):putchar(*p):--*p:++*p:--p:++p;
            if(c==91)f(a,!*p);
            else if(c==93){if(!*p)return;else a=r;}
        }
        else
        {
            if(c==93)
            {
                --s;
                if(!*p&&!s)return;
            }
            else if(c==91)
            {
                s++;
            }
        }
    }
}

main(int c,char**v){
    fread(z,1,9999,fopen(*++v,"r"));
    a=z;
    f(0,0);
}

тесты:

Привет, мир

Rot13


Проверяете ли вы один и тот же указатель ( l) каждый раз, когда выполняете цикл? Я думаю, что вы должны проверить текущее местоположение головы ( p).
Александру

Я передаю указатель на буфер и указатель на поток. В конце цикла он проверяет, lдостиг ли нуля указатель в буфере, и прерывает его, иначе он сбрасывает поток обратно в исходный цикл [. Это необходимо для вложенных [циклов.
snmcdonald

1
Да уж. Я так и думал. Вы не должны проверять значение указателя при первом входе в цикл, но значение текущего указателя. Проверьте тест в вопросе. Ваша программа зависает.
Александру

1
Вы можете заменить break;elseна return;.
Александру

3
Я думаю, что вы можете заменить (c==62)?a:bна (c-62)?b:a.
Александру

9

PHP 5.4, 296 294 273 263 261 209 191 183 178 166 символов:

Я дал ему шанс, не используя eval, но в конце концов мне пришлось его использовать

<?$b=0;eval(strtr(`cat $argv[1]`,["]"=>'}',"["=>'while($$b){',"."=>'echo chr($$b);',","=>'$$b=fgetc(STDIN);',"+"=>'$$b++;',"-"=>'$$b--;',">"=>'$b++;',"<"=>'$b--;']));

Все команды работают. Это сильно злоупотребляет переменными и выдает предупреждения. Однако, если кто-то изменит свой php.ini на предупреждения с подавлением (или отправит stderr в / dev / null), это прекрасно работает.

Подтверждение (это пример "Hello World!" Из Википедии ): http://codepad.viper-7.com/O9lYjl

Ungolfed, 367 365 335 296 267 символов:

<?php
$a[] = $b = 0;
$p = implode("",file($argv[1])); // Shorter than file_get_contents by one char
$m = array("]" => '}', "[" => 'while($a[$b]){',"." => 'echo chr($a[$b]);', "," => '$a[$b]=fgetc(STDIN);', "+" => '$a[$b]++;', "-" => '$a[$b]--;', ">" => '$b++;', "<" => '$b--;');
$p = strtr($p,$m);
@eval($p);

Это должно быть запущено через командную строку: php bf.php hello.bf


8

Windows PowerShell, 204

'$c=,0*3e4;'+@{62='$i++
';60='$i--
';43='$c[$i]++
';45='$c[$i]--
';44='$c[$i]=+[console]::ReadKey().keychar
';46='write-host -n([char]$c[$i])
';91='for(;$c[$i]){';93='}'}[[int[]][char[]]"$(gc $args)"]|iex

Довольно простое преобразование инструкций, а затем Invoke-Expression.

История:

  • 2011-02-13 22:24 (220) Первая попытка.
  • 2011-02-13 22:25 (218) 3e4короче 30000.
  • 2011-02-13 22:28 (216) Ненужные разрывы строк. Соответствие по целым числам вместо символов короче.
  • 2011-02-13 22:34 (207) Использовали индексы в хеш-таблицу вместо switch.
  • 2011-02-13 22:40 (205) Лучшее приведение к строке удаляет две скобки.
  • 2011-02-13 22:42 (204) Не нужно пробела после аргумента Write-Host.

8

C, 333 символа

Это мой первый переводчик BF и первый гольф, который мне пришлось отлаживать.

Это запускает генератор простых чисел в Mac OS X / GCC, но #include<string.h>может потребоваться дополнительное по цене еще 19 символов, если неявное определение strchrне работает на другой платформе. Также это предполагает O_RDONLY == 0. Кроме того, intисключение из объявления Mсохранения 3 символов, но это не соответствует требованиям C99. То же самое с третьим *в b().

Это зависит от особенностей кодирования ASCII. Все операторы Brainfuck являются дополнительными парами, разделенными расстоянием 2 в кодовом пространстве ASCII. Каждая функция в этой программе реализует пару операторов.

#include<unistd.h>
char C[30000],*c=C,o,P[9000],*p=P,*S[9999],**s=S,*O="=,-\\",*t;
m(){c+=o;}
i(){*c-=o;}
w(){o<0?*c=getchar():putchar(*c);}
b(){if(o>0)*c?p=*s:*--s;else if(*c)*++s=p;else while(*p++!=93)*p==91&&b();}
int(*M[])()={m,i,w,b};
main(int N,char**V){
read(open(V[1],0),P,9e3);
while(o=*p++)
if(t=strchr(O,++o&~2))
o-=*t+1,
M[t-O]();
}

Я думаю, что вы можете уменьшить его, используя обозначение «е» для всех больших чисел.
Люзер Дрог

@luser: Сначала я тоже был удивлен, но язык и компилятор этого не допустят. Мне удалось сжать еще 4 символа с помощью твиков, и использование #defineтаблицы функций вместо таблицы также могло бы быть более кратким. Мне просто нравится число 333 и таблица: v).
Potatoswatter

О верно. Я действительно должен был это знать. Электронная нотация находится в производстве для константы с плавающей точкой, тогда как для объявления требуется целое число. Кстати, это может быть мошенничеством, но посмотрите версию nieko.net/projects/brainfuck Урбана Мюллера. Самый большой выигрыш, кажется, интенсивное использование ||.
Люзер Дрог

8

CJam, 75 байтов

lq3e4Vc*@{"-<[],.+>"#"T1$T=(t T(:T; { _T=}g \0+(@T@t _T=o "_'(')er+S/=}%s~@

Попробуйте онлайн: реверсер строк , Hello World .

объяснение

Принимает код в первой строке STDIN и вводит все строки под ним.

l            Read a line from STDIN (the program) and push it.
 q           Read the rest of STDIN (the input) and push it.
  3e4Vc*     Push a list of 30000 '\0' characters.
        @    Rotate the stack so the program is on top.

{               }%   Apply this to each character in prog:
 "-<[],.+>"#         Map '-' to 0, '<' to 1, ... and everything else to -1.
            ...=     Push a magical list and index from it.

s~       Concatenate the results and evaluate the resulting string as CJam code.
  @      Rotate the top three elements again -- but there are only two, so the
         program terminates.

Как насчет этого волшебного списка?

"T1$T=(t T(:T; { _T=}g \0+(@T@t _T=o "  Space-separated CJam snippets.
                                        (Note the final space! We want an empty
                                        string at the end of the list.)
_'(')er+                                Duplicate, change (s to )s, append.
        S/                              Split over spaces.

Полученный список выглядит следующим образом:

T1$T=(t    (-)
T(:T;      (<)
{          ([)
_T=}g      (])
\0+(@T@t   (,)
_T=o       (.)
T1$T=)t    (+)
T):T;      (>)
{          (unused)
_T=}g      (unused)
\0+(@T@t   (unused)
_T=o       (unused)
           (all other characters)

Мы генерируем фрагменты для +и >из тех, для -и <просто путем замены левых паренов («декремент» CJam) на правые («приращение» CJam).


Кратчайший ответ и самый большой победитель
Джек Гиффин

7

F #: 489 символов

Следующая программа не выполняет инструкции '[' / ']', но сканирует исходный код для следующего соответствующего токена. Это, конечно, делает его довольно медленным, но он все равно может найти простые числа меньше 100. Целочисленные типы F # не переполняются, а переносятся.

Вот короткая версия:

[<EntryPoint>]
let M a=
 let A,B,i,p,w=Array.create 30000 0uy,[|yield!System.IO.File.ReadAllText a.[0]|],ref 0,ref 0,char>>printf"%c"
 let rec g n c f a b=if c then f i;if B.[!i]=a then g(n+1)c f a b elif B.[!i]=b then(if n>0 then g(n-1)c f a b)else g n c f a b
 while !i<B.Length do(let x=A.[!p]in match B.[!i]with|'>'->incr p|'<'->decr p|'+'->A.[!p]<-x+1uy|'-'->A.[!p]<-x-1uy|'.'->w x|','->A.[!p]<-byte<|stdin.Read()|'['->g 0(x=0uy)incr '['']'|']'->g 0(x>0uy)decr ']''['|_->());incr i
 0

Неприятным моментом было то, что программа primes.bf захлебывается окнами новой строки. Чтобы запустить его, я должен был сохранить введенный номер в текстовом документе в формате UNIX и передать его в программу с конвейером:

interpret.exe prime.bf < number.txt

Изменить: ввод Alt + 010 с последующим Enter также работает в Windows cmd.exe

Вот более длинная версия:

[<EntryPoint>]
let Main args =
    let memory = Array.create 30000 0uy
    let source = [| yield! System.IO.File.ReadAllText args.[0] |]
    let memoryPointer = ref 0
    let sourcePointer = ref 0
    let outputByte b = printf "%c" (char b)
    let rec scan numBraces mustScan adjustFunc pushToken popToken =
        if mustScan then
            adjustFunc sourcePointer
            if source.[!sourcePointer] = pushToken then
                scan (numBraces + 1) mustScan adjustFunc pushToken popToken
            elif source.[!sourcePointer] = popToken then
                if numBraces > 0 then scan (numBraces - 1) mustScan adjustFunc pushToken popToken
            else
                scan numBraces mustScan adjustFunc pushToken popToken 

    while !sourcePointer < source.Length do
        let currentValue = memory.[!memoryPointer]
        match source.[!sourcePointer] with
            | '>' -> incr memoryPointer
            | '<' -> decr memoryPointer
            | '+' -> memory.[!memoryPointer] <- currentValue + 1uy
            | '-' -> memory.[!memoryPointer] <- currentValue - 1uy
            | '.' -> outputByte currentValue
            | ',' -> memory.[!memoryPointer] <- byte <| stdin.Read()
            | '[' -> scan 0 (currentValue = 0uy) incr '[' ']'
            | ']' -> scan 0 (currentValue > 0uy) decr ']' '['
            |  _  -> ()
        incr sourcePointer
    0 

Я решил проблему с Enter, не нажимая ее, а нажав Ctrl + J :-)
Joey

Ctrl + J у меня не сработал, но ввод Alt + 010 и Enter позволил.
cfern

7

Delphi, 397 382 378 371 366 364 328 символов

Съешь этот Дельфи!

328 var p,d:PByte;f:File;z:Word=30000;x:Int8;begin p:=AllocMem(z+z);d:=p+z;Assign(F,ParamStr(1));Reset(F,1);BlockRead(F,p^,z);repeat z:=1;x:=p^;case x-43of 1:Read(PChar(d)^);3:Write(Char(d^));0,2:d^:=d^+44-x;17,19:d:=d+x-61;48,50:if(d^=0)=(x=91)then repeat p:=p+92-x;z:=z+Ord(p^=x)-Ord(p^=x xor 6);until z=0;end;Inc(p)until x=0;end.

Здесь тот же код с отступом и комментарием:

var
  d,p:PByte;
  x:Int8;
  f:File;
  z:Word=30000;
begin
  // Allocate 30000 bytes for the program and the same amount for the data :
  p:=AllocMem(z+z);
  d:=p+z;
  // Read the file (which path must be specified on the command line) :
  Assign(F,ParamStr(1));
  Reset(F,1);
  BlockRead(F,p^,z);
  // Handle all input, terminating at #0 (better than the spec requires) :
  repeat
    // Prevent a begin+end block by preparing beforehand (values are only usable in '[' and ']' cases) :
    z:=1;                       // Start stack at 1
    x:=p^;                      // Starting at '[' or ']'
    // Choose a handler for this token (the offset saves 1 character in later use) :
    case x-43of
      1:Read(PChar(d)^);        // ','     : Read 1 character from input into data-pointer
      3:Write(Char(d^));        // '.'     : Write 1 character from data-pointer to output
      0,2:d^:=d^+44-x;          // '+','-' : Increase or decrease data
      17,19:d:=d+x-61;          // '<','>' : Increase or decrease data pointer
      48,50:                    // '[',']' : Start or end program block, the most complex part :
        if(d^=0)=(x=91)then     // When (data = 0 and forward), or when (data <> 0 and backward)
        repeat                  //
          p:=p+92-x;            // Step program 1 byte back or forward
          z:=z+Ord(p^=x)        // Increase stack counter when at another bracket
              -Ord(p^=x xor 6); // Decrease stack counter when at the mirror char
        until z=0;              // Stop when stack reaches 0
    end;
    Inc(p)
  until x=0;
end.

Этот занял у меня несколько часов, так как это не тот код, который я обычно пишу, но мне нравится!

Примечание: основной тест работает, но не останавливается на 100, потому что он читает # 13 (CR) до # 10 (LF) ... другие заявки тоже страдают от этой проблемы при работе в ОС CRLF?


Вау! Я никогда бы не ожидал превзойти С в краткости с Дельфи! Нет, пока вы не примените мои идеи к
догадкам

7

C 260 + 23 = 283 байта

Я создал программу на C, которую можно найти здесь .

main(int a,char*s[]){int b[atoi(s[2])],*z=b,p;char*c=s[1],v,w;while(p=1,
*c){q('>',++z)q('<',--z)q('+',++*z)q('-',--*z)q('.',putchar(*z))q(',',*z
=getchar())if(*c=='['||*c==']'){v=*c,w=184-v;if(v<w?*z==0:*z!=0)while(p)
v<w?c++:c--,p+=*c==v?1:*c==w?-1:0;}c++;}}

Должен быть скомпилирован с помощью gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.cи может быть вызван следующим образом: pmmbf ",[.-]" 30000при этом первый аргумент (в кавычках) содержит bf-программу для запуска, второй определяет, насколько большой должна быть лента.


1
Я думаю, что вам нужно добавить 23 символа к вашему счету для этой -D"q(a,b)"="*c-a||(b);"опции, так как это (насколько я понимаю, по крайней мере) помогает уменьшить ваш код.
Гарет

Опция включена в размещенный текст. Причина этого заключается в том, чтобы избегать длинных слов defineи новой строки, но я не думаю, что это действительно кошерное. Во всяком случае, с цитатами, комментариями, и gcc -Dя не вижу преимущества вообще.
Potatoswatter

5

С 267

#define J break;case
char*p,a[40000],*q=a;w(n){for(;*q-93;q++){if(n)switch(*q){J'>':++p;J'<':--p;J'+':++*p;J'-':--*p;J'.':putchar(*p);J',':*p=getchar();}if(*q==91){char*r=*p&&n?q-1:0;q++;w(r);q=r?r:q;}}}main(int n,char**v){p=a+read(open(v[1],0),a,9999);*p++=93;w(1);}

Запустите как ./a.out primes.bf

Безголовая версия:

#define J break;case

char*p,a[40000],*q=a; // packed so program immediately followed by data

w(n){
    for(;*q-93;q++){ // until ']'
        if(n)switch(*q){ // n = flagged whether loop evaluate or skip(0)
                J'>':++p;
                J'<':--p;
                J'+':++*p;
                J'-':--*p;
                J'.':putchar(*p);
                J',':*p=getchar();
        }
        if(*q==91){char*r=*p&&n?q-1:0;q++;w(r);q=r?r:q;} // recurse on '[', record loop start
    }
}

main(int n,char**v){
    p=a+read(open(v[1],0),a,9999);
    *p++=93; // mark EOF with extra ']' and set data pointer to next
    w(1); // begin as a loop evaluate
}

5

Python 2, 223

Я признаю, что переработал мою старую программу (но мне пришлось немного ее изменить, потому что в старой версии не было ввода, но была проверка ошибок ...).

P="";i,a=0,[0]*30000
import os,sys
for c in open(sys.argv[1]).read():x="><+-.[,]".find(c);P+=" "*i+"i+=1 i-=1 a[i]+=1 a[i]-=1 os.write(1,chr(a[i])) while+a[i]: a[i]=ord(os.read(0,1)) 0".split()[x]+"\n";i+=(x>4)*(6-x)
exec P

Хорошо запускает калькулятор простых чисел.

Теперь я вижу, что у Александру есть ответ, который имеет некоторые сходства. В любом случае я выложу mny answer, потому что я думаю, что в этом есть новые идеи.


5

C (gcc) Linux x86_64, 884 621 525 487 439 383 358 354 байта

*z,*mmap();d[7500];(*p)();*j(a,g)char*a;{char*t=a,*n,c,q=0;for(;read(g,&c,!q);)t=c==91?n=j(t+9,g),z=mempcpy(t,L"\xf003e80Ƅ",5),*z=n-t-9,n:c==93?q=*t++=233,z=t,*z=a-13-t,z+1:stpcpy(t,c-62?c-60?c-43?c-45?c-46?c-44?"":"1\xc0P_\xF\5":"RXR_\xF\5":L"໾":L"۾":L"컿":L"웿");return t;}main(P,g)int**g;{p=mmap(0,1<<20,6,34,0,0);p(*j(p,open(g[1],0))=195,d,1);}

Попробуйте онлайн!

Это JIT, который компилирует код BF в машинный язык x86_64 во время выполнения. Это выполняет прямую трансляцию так часто встречающуюся последовательности , такие как >>>, <<<, +++и ---не соединилось в более быстрые инструкции.

Менее гольф-версия:

// size of data area
*z,c,*mmap();d[7500];(*p)();
// recursive function translates BF commands to x86_64 instructions
*j(a,g)char*a;{
  char*t=a,*n,q=0;
  for(;read(g,&c,!q);)
    t=c==91? // [
        // cmpb $0x0,(%rsi)
        // je n-t-9
        n=j(t+9,g),
        z=mempcpy(t,L"\xf003e80Ƅ",5)
        *z=n-t-9,
        n
      :
        c==93? // ]
          // jmp a-13-t
          q=*t++=233,
          z=t,
          *z=a-13-t,
          z+1
        :
          stpcpy(t,c-62? // >
                     c-60? // <
                       c-43? // +
                         c-45? // -
                           c-46? // .
                             c-44? // ,
                               ""
                             :
                               // xor %eax,%eax
                               // push %rax
                               // pop %rdi
                               // syscall
                               "1\xc0P_\xF\5"
                           :
                             // push %rdx
                             // pop %rax
                             // push %rdx
                             // pop %rdi
                             // syscall
                             "RXR_\xF\5"
                         :
                           // decb (%rsi)
                           L"໾"
                       :
                         // incb (%rsi)
                         L"۾"
                     :
                       // dec %esi
                       L"컿"
                   :
                     // inc %esi
                     L"웿");
  return t;
}
main(P,g)int**g;{
  // allocate text (executable) memory and mark as executable
  p=mmap(0,1<<20,6,34,0,0);
  // run JIT, set %rdx=1 and call code like a function
  p(*j(p,open(g[1],0))=195,d,1);
}

4

С 374 368

Читает из файла. Проходит тест PRIME.BF.

Использование: ./a.out PRIME.BF

#include <stdio.h>
main(int c,char**v){int m[30000],s[99],p=0,i=0,n=0;char l[9999],d;FILE*f=fopen(v[1],"r");for(l[i]=0;i<9999&&l[i]!=EOF;l[i]=getc(f))i++;for(i=1;d=l[i];i++){if(!n){p+=d-62?0:1;p-=d-60?0:1;m[p]+=d-43?0:1;m[p]-=d-45?0:1;if(d==46)putchar(m[p]);if(d==44){m[p]=getchar();}if(d==93){i=s[c]-1;c--;n++;}}if(d==91){if(m[p]){c++;s[c]=i;}else{n++;}}n-=d-93?0:1;}}


переформатирован:

#include <stdio.h>
main(int c,char**v){
    int m[3000],s[99],p=0,i=0,n=0;
    char l[9999],d;
    FILE*f=fopen(v[1],"r");
    for(l[i]=0;i<9999&&l[i]!=EOF;l[i]=getc(f))i++;
    for(i=1;d=l[i];i++){
        if(!n){ // > < + - . , ] \n [ ]
            p+=d-62?0:1;
            p-=d-60?0:1;
            m[p]+=d-43?0:1;
            m[p]-=d-45?0:1;
            if(d==46)putchar(m[p]);
            if(d==44){m[p]=getchar();}
            if(d==93){i=s[c]-1;c--;n++;}
        }
        if(d==91){if(m[p]){c++;s[c]=i;}else{n++;}}
        n-=d-93?0:1;
    }
}

3000 против 30000. Ваш буфер слишком мал. Размер программы также слишком мал.
Александру

Я сделал опечатку, исправлено. Что вы подразумеваете под размером программы? Если вы имеете в виду максимальный размер файла, вы не указали минимальный размер, который он должен обрабатывать.
Jtjacques

4

Луа, 285

loadstring("m,p={0},1 "..io.open(arg[1]):read"*a":gsub("[^.,<>[%]+-]",""):gsub(".",{["."]="io.write(string.char(@)) ",[","]="@=io.read(1):byte() ",["<"]="p=p-1 ",[">"]="p=p+1 @=@or 0 ",["["]="while @~=0 do ",["]"]="end ",["+"]="@=(@+1)%256 ",["-"]="@=(@-1)%256 "}):gsub("@","m[p]"))()

Несколько читаемая версия:

loadstring( --execute
    "m,p={0},1 ".. --initialize memory and pointer
    io.open(arg[1]) --open file
        :read"*a" --read all
            :gsub("[^.,<>[%]+-]","") --strip non-brainfuck
                :gsub(".", --for each character left
                    {["."]="io.write(string.char(@)) ", -- '@' is shortcut for 'm[p]', see below
                    [","]="@=io.read(1):byte() ",
                    ["<"]="p=p-1 ",
                    [">"]="p=p+1 @=@or 0 ", --if a before unexplored memory cell, set to 0
                    ["["]="while @~=0 do ",
                    ["]"]="end ",
                    ["+"]="@=(@+1)%256 ", --i like it overflowing
                    ["-"]="@=(@-1)%256 "
                    }
                )
                    :gsub("@","m[p]") --replace the '@' shortcut
    ) --loadstring returns a function
() --call it

Работает отлично

Луа, 478, без нагрузки

local m,p,i,r,c={0},1,1,{},io.open(arg[1]):read"*a"while i<=#c do(({[43]=function()m[p]=(m[p]+1)%256 end,[45]=function()m[p]=(m[p]-1)%256 end,[62]=function()p=p+1 m[p]=m[p]or 0 end,[60]=function()p=p-1 end,[46]=function()io.write(string.char(m[p]))end,[44]=function()m[p]=io.read(1):byte()end,[91]=function()if m[p]==0 then i=select(2,c:find("%b[]",i))else r[#r+1]=i end end,[93]=function()if m[p]==0 then r[#r]=nil else i=r[#r] end end})[c:byte(i)]or function()end)()i=i+1 end

Читаемая версия:

local m,   p, i, r,  c= --memory, pointer, brackets stack, code
      {0}, 1, 1, {}, io.open(arg[1]) --open file
              :read"*a" --read it
while i<=#c do --while there's code
    (
        (
            {
                [43]=function() -- +
                    m[p]=(m[p]+1)%256
                end,
                [45]=function() -- -
                    m[p]=(m[p]-1)%256
                end,
                [62]=function() -- >
                    p=p+1 m[p]=m[p]or 0 --if new memory cell, set it to 0
                end,
                [60]=function() -- <
                    p=p-1
                end,
                [46]=function() -- .
                    io.write(string.char(m[p]))
                end,
                [44]=function() -- ,
                    m[p]=io.read(1):byte()
                end,
                [91]=function() -- [
                    if m[p]==0 then
                        i=select(2,c:find("%b[]",i)) --find matching ]
                    else
                        r[#r+1]=i --push position to the stack
                    end
                end,
                [93]=function() -- ]
                    if m[p]==0 then
                        r[#r]=nil --pop from stack
                    else
                        i=r[#r] --go to position on the top of stack
                    end
                end
            }
        )[c:byte(i)] --transform character into code
        or function()end --do nothing on non-brainfuck
    )() --run the resulting function
    i=i+1 --go to the next opcode
end

4

Brainfuck, 948 байт

Ну, это заняло некоторое время. Я играю в брейнфукский самоинтерпретатор ... не мной.

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

4

Напомним , 594 байта

Вкратце: Recall не имеет арифметических операторов в классическом смысле, он имеет только побитовые операции. Вы не можете просто «добавить один» и т. Д. Напомним, также строго на основе стека.

DC505M22022M32032M606M42042M707M92092M4405022o032o06o042o07o092o044o1305022o06o042o092o52052q.q2305022o06o07o93093q.q5403206o07o14014q.q6403206o042o07o24024q.q74Yx34034z03MMMMMMMM034o3yY030401r3.4.101zyY040301r4.3.101zY01052gZ02Z040301052023s4.3.10zyY01023gZ02z030401023052s3.4.10zyY01093gZ02q20zyY01054gZ02u20zyY01014gZx20zyY01064gZ02X0zyY01024gZ03304302r33.43.20zyY01074gZ04303302r43.33.20zyyQ6205.8Y06208g6206208iZ08M808013izy062U7205.9Y07209g7207209iz09M909013izy072R53.63.82063MMMMMMMM053o63082013i53082KKKKKKKK82053063082S84.94.12.73.83t012073083TY083073012r83.73.12012084gzY012094gZt0zyy

Пример 1. Напечатайте что-нибудь

Входные данные:

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

Выход:

PPCG rocks!

Пример 2. Выведите квадратные числа до 100

Входные данные:

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

Выход:

0
1
4
9
16
25
36
49
64
81
100

Этот пример может занять несколько минут для выполнения и может вызвать сообщение «эта вкладка заморожена». Проигнорируйте это и подождите.


4
Срок действия домена вашего сайта истек. Кроме того, этот ответ не является конкурирующим, потому что язык новее, чем вызов.
mbomb007

3

OCaml (lex), 497 символов

OCamllex является частью стандартного дистрибутива OCaml.

{let a=Array.create 30000 0
let(%)f g h=f(g h)
let s v i=a.(i)<-v;i
let o d i=s(a.(i)+d)i
let p i=print_char(Char.chr a.(i));flush stdout;i
let r i=s(Char.code(input_char stdin))i
let rec w g i=if 0=a.(i)then i else w g(g i)
let n x=x}
rule t f=parse
|'>'{t(succ%f)lexbuf}
|'<'{t(pred%f)lexbuf}
|'+'{t((o 1)%f)lexbuf}
|'-'{t((o(-1))%f)lexbuf}
|'.'{t(p%f)lexbuf}
|','{t(r%f)lexbuf}
|'['{t((w(t n lexbuf))%f)lexbuf}
|']'|eof{f}
|_{t f lexbuf}
{let _=t n(Lexing.from_channel(open_in Sys.argv.(1)))0}

Сохранить как b.mll и запустить с

ocamllex b.mll && ocaml b.ml prime.bf

Я не люблю синтаксический анализ вручную, поэтому я использовал предоставленный генератор лексеров. Из прочитанных токенов мы составляем функцию для всей программы brainf * ck.


3

C # (2861 символ, ~ 84 строки)

Это не самое красивое решение проблемы, и, возможно, не все, что касается игры в гольф, поскольку я не был так озабочен длиной, как следовало бы. (Я не удалил комментарии или лишние пробелы.) Я просто хотел попробовать что-то на новом языке, чтобы посмотреть, смогу ли я. Если бы я сделал это снова, я бы отказался от использования стека для возврата из ']' и просто оглянулся назад. Запуск без аргументов командной строки запускает программу hello world, указанную в описании проблемы. Он принимает один аргумент командной строки, имя файла программы для запуска.

using System;
using System.Collections.Generic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            String ProgSource;
            if (args.Length > 0)
                ProgSource = System.IO.File.ReadAllText(args[0]);
            else //hello world
                ProgSource = "";

            Stack<int> stack = new Stack<int>();
            char[] bfProg = ProgSource.ToCharArray();
            char[] mem = new char[30000];
            int ptr = 0;

            for (int ip = 0; ip<bfProg.Length; ip++){
                switch (bfProg[ip])
                {
                    case ('>'): ptr++;  break;
                    case ('<'): ptr--;  break;
                    case ('+'): mem[ptr]++; break;
                    case ('-'): mem[ptr]--; break;
                    case ('.'): Console.Write(mem[ptr]); break;
                    case (','): 
                        char key = Console.ReadKey(false).KeyChar;
                        if (key == '\r')
                        {
                            key = (char)10;
                            Console.WriteLine();
                        }
                        mem[ptr] = key;
                        break;
                    case ('['):
                        if (mem[ptr] == 0)
                        {
                            int openBraces = 1;
                            //find the closing brace for this expression
                            for (int x = 1; x < (bfProg.Length - ip); x++)
                            {
                                if (bfProg[ip + x] == ']') openBraces--;
                                if (bfProg[ip + x] == '[') openBraces++;
                                if (openBraces == 0)
                                {
                                    if (stack.Peek() == ip) stack.Pop();
                                    ip += x;
                                    break;
                                }                                
                            }
                       }
                       else
                       {
                           stack.Push(ip);
                       }
                       break;
                    case (']'):
                        if (mem[ptr] == 0)
                            stack.Pop();
                        else
                        {
                            ip = stack.Peek();
                        }
                        break;
                }
            }

            Console.WriteLine("\n\n\nExecution Completed Sucessfully. Press any key to continue...");
            Console.ReadKey();

        }
    }

}

Изменить: Удалены неиспользованные ссылки.


1
@ mbomb007 - Обновлено. Полностью забыл, я даже сделал это. (Даже не подозревал, что кто-то даже читал эти старые вопросы)
theB

Мало того, что люди все еще читают их, они все еще отвечают и играют в гольф их.
mbomb007

3

C (gcc) , 273 268 байт

main(_,a){_=fopen("w.c","w");fputs("main(){char a[30000],*p=a;",_);x:a=getchar();fputs(a-62?a-60?a-43?a-45?a-46?a-44?a-91?a-93?~a?"":"}":"}":"while(*p){":"*p=getchar();":"putchar(*p);":"--*p;":"++*p;":"--p;":"++p;",_);if(~a)goto x;fclose(_);system("cc w.c;./a.out");};

Попробуйте онлайн!

-5 благодаря потолку

Принимает ввод от стандартного ввода.

Это немного зависит от окружающей среды, но довольно последовательно. Это эффективное решение для c. Он записывает соответствующую C-программу в файл wc, компилирует ее и запускает как нужный исполняемый файл. Таким образом, в качестве бонусного эффекта это на самом деле компилирует код bf и оставляетa.out для него двоичный код. Обратите внимание, что в зависимости от системы вам может потребоваться изменить последнюю строку. В частности, большинство компиляторов Windows c называют исполняемый файл по умолчанию «a.exe». К счастью, насколько я могу судить, все они имеют одинаковую длину, поэтому количество пользователей одинаково. (хотя, если вы не определили cc, вам может понадобиться добавить букву, такую ​​как gcc, в команду компиляции, добавив 1 байт).

Я знаю, что этот поток немного староват, но я еще не видел этот стиль C-решения, поэтому я решил добавить его.



2

[РЕДАКТИРОВАТЬ]

C ++ 11, 355, читает из файла:

#include<functional>
#include<stdio.h>
main(){
char b[30000],g[9999],*f=g,*p=b,n[]="+-,.><[]",j;
std::function<void()>m[]={
[&p]{(*p)++;},
[&p]{(*p)--;},
[&p]{*p=getchar();},
[&p]{putchar(*p);},
[&p]{p++;},
[&p]{p--;},
[&p,&f]{if(!(*p))while(*f-93)f++;},
[&f,&m]{while(*f-91)f--;m[6]();}
};
fread(g,1,9999,fopen(a[1],0));
for(;*f;f++)for(j=0;n[j];j++)if(n[j]==*f)m[j]();
}

Контрольная работа

http://ideone.com/b7vO4

[СТАРАЯ ВЕРСИЯ]

C ++ 11, 391, чтобы увидеть работает: http://ideone.com/yZHVv

#include<functional>
#include<stdio.h>
main(int c,char **a) {
  char b[30000],g[9999],*f=g,*r=f,*p=b;
  std::function<void()>m[256];
  m['>']=[&p]{p++;};  
  m['<']=[&p]{p--;};
  m['+']=[&p]{(*p)++;};
  m['-']=[&p]{(*p)--;};
  m['.']=[p]{putchar(*p);};
  m[',']=[&p]{*p=getchar();};
  m['[']=[p,&r,&f]{*p?r=f-1:r=0;};
  m[']']=[&r,&f]{r?f=r:r=f;};
  fread(g,1,9999,fopen(a[1],"r"));
  while (c=*(f++))if(m[c]&&(r||c==']'))m[c]();
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.