Інтерпретувати brainf ***


113

Написати найкоротшу програму в вашому улюбленому мовою інтерпретувати Brainfuck програму. Програма читається з файлу. Вхід і вихід - це стандартний вхід і стандартний вихід.

  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) обведена пам’ять 4) можливо будь-які інші деталі
Накілон

3
Цікаво, чи повинні бути дві категорії: ті програми, які використовують eval (або оболонку для компіляції), - і ті, які цього не роблять.
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: Введіть програму Slurp $_та перетворіть її на код Perl за допомогою таблиці перекладу. На undefцьому кроці коментарі автоматично знімаються (замінюються ).

Крок 2: Скасуйте всі $b[$p]події

Крок 3: Запустіть програму за допомогою eval.


Просто використовуйте Perl в qwсинтаксис для визначення %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+

EDIT

Ось деякий асемблер (стиль 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, спричиняють вихід програми, а не ігнорування. Це легко виправити, і я залишу це як вправу для людей, щоб зробити це самі.
Скізз

Пам’ятаю, я отримав версію 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

Рубін 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. Технічні характеристики кажуть, що не підписано, а переповнення не визначено.
анонімний боягуз

3e4також буде працювати на відміну від30000
анонімний боягуз

@Charlie: Дякую Хоча, щоб бути справедливим, він не сказав "без підпису", коли я писав код. Я, чесно кажучи, не знав, що ти можеш написати 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
Чому це взагалі існує? Мабуть, воно навіть існує у царині досліджень . Оо
Ісія Медоуз

Так що це не спрацює з коментованими програмами, що займаються мозком?
kamoroso94

Ні, не без спершу викреслюючи коментарі.
Джон Тромп

18

Сітківка 0,8.2 , 386 391 386 байт

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

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

Приймає вхід як <code>│<input>. Ні, це не труба ( |). Це символ Unicode 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>, де перша - покажчик коду, а друга - покажчик стрічки.

ÿє 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

Якщо у вас немає способу підключення калькулятора до комп'ютера, і ви хочете набрати це на calc (замість цього я не уявляю, чому ви хочете, але я відхилився) зауважте, що ->це STO>кнопка над УВІМКНЕНО key ~- це негативний символ поруч із клавішею ENTER та замінити всі екземпляри L<number>відповідним маркером списку, знайденим на2ND -> <number on keypad>

Завдяки thomas-kwa (принаймні, я думаю, що це його ім'я Stack), що допомагає мені оптимізувати це, особливо з інструкціями [та ]інструкціями.


1
Вам потрібні парени навколо Ans+S?
Zacharý

@ Zacharý Хороший улов, ні. Я, мабуть, був невпевнений у тому, як працює PEMDAS чи щось таке ... Я утримаюсь від редагування, однак, тому що це було так довго, що напевно не варто навантажувати цю посаду на фронт і тому, що двобайтовий скорочення не дасть відповіді будь-якої переваги перед іншими, хай.
MI MI Райт

1
Я пам’ятаю, як 2-3 роки тому, коли я використовував цю програму для тлумачення Brainf *** на своєму калькуляторі. І, це питання інтерпретації brainf ***, я думаю, воно повинно бути вгорі, щоб бути чесним.
Zacharý

1
Власне, я думаю, що ця лінія могла бути S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. ( a-a=0). І ей, не турбуйся про те, що забудеш ОДИН порядок операцій тут, я бачив, що ціла кількість людей забуває порядок операцій для %(mod) на виклик.
Zacharý

1
О, да, так. Гаразд, це дає щонайменше 10 байт, оскільки якщо можна зробити однолінійку, а також деякі інші речі ... може також редагувати. Ви змусили мене вперше, як за рік, витягнути свій калькулятор, щоб перевірити цей матеріал, ха-ха
MI Райт

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
Акуратно, ви генеруєте вихідний код python, використовуючи brainfuck.

1
Ви можете зняти 1 char, "import sys as s" та замінити "sys" на "s" у решті
ВАС

Зауважте, що це насправді 247 символів. (Дивіться гидкий простір після exec t?). Якщо ви використовуєте підказку S.Mark , а також зробите весь forцикл в один рядок, ви можете зменшити це до 243 знаків.
Олег Припін

Це не вдається на будь-якому вході, що містить []дійсну, хоча і тривіальну програму bf. Я запропонував редагування, яке виправляє це, але збільшує кількість символів. Щоб додатково зменшити кількість символів, ви можете from sys import *та використовувати їх 'i+=1,...'.split(',')замість ['i+=1',...].
кабінка

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 

update 2011-02-15: Включені пропозиції JB, трохи перейменувавшись і посилившисьmain


1
Ви повинні мати змогу отримати буферизацію від справедливих IO, а аргументи - від просто System(-19). Проблема буферизації мене також турбує, оскільки специфікація насправді не згадує про це, а відповідь, що голосує в голові, навіть не робить I / O. Якщо вам потрібно зберегти його, можливо, 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.

Безголовки:

#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 на попередження про щеплення (або труби більш жорсткі на / dev / null), це чудово працює.

Перевірка (це приклад "Привіт, світ!" З Вікіпедії ): 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]();
}

Я думаю, ви можете більше зменшити його, використовуючи позначення 'e' для всіх великих чисел.
luser droog

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

О, так. Я справді мав це знати. E-позначення виробляється для постійної з плаваючою комою, тоді як декларація вимагає цілого числа. До речі, це може бути обманом, але ознайомтеся з nieko.net/projects/brainfuck за версією Urban Müller. Найбільший прибуток, як видається, велике використання ||.
luser droog

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 символів

Їжте цю Delphi!

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?


Оце Так! Я ніколи не сподівався б натрапити на C у лагідності з Delphi! Поки ви не застосуєте мої ідеї до CI здогадується ;-)
PatrickvL

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

Пітон 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 відповідь, тому що я думаю, що в цьому є нові ідеї.


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 байт

Ну, це зайняло деякий час. Я пограв у самовідповідача Brainfuck ... не я.

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

4

Нагадаємо , 594 байти

Якщо коротко: Нагадаємо, у класичному сенсі немає арифметичних операторів, у них є лише побітові операції. Ви не можете просто "додати" тощо. Нагадаємо, також суворо базується на стеках.

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 char, ~ 84 рядків)

Це не найкрасивіший варіант вирішення проблеми, і, мабуть, не все, що "Гольф-іш", оскільки я не так хвилювався довжиною, як, напевно, мав би бути. (Я не видалив коментарі чи зайвий пробіл.) Я просто хотів спробувати щось новою мовою, щоб побачити, чи зможу я. Якби я це зробив ще раз, я б відмовився від використання стека для повернення з ']' і просто озирнусь назад. Запустившись без аргументів командного рядка, він запускає програму привіт, що міститься в описі проблеми. Він приймає один аргумент командного рядка, ім'я файлу програми для запуску.

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 завдяки плафоні

Бере вхід з stdin.

Це трохи покладається на навколишнє середовище, але досить послідовно. Це ефективно рішення eval для c. Він записує відповідну програму C у файл wc, компілює її та запускає її як потрібний виконуваний файл. Таким чином, як бонусний ефект, це фактично компілює bf-код і залишає a.outйого двійковим. Зауважте, що залежно від системи вам може знадобитися змінити останній рядок. Зокрема, більшість компіляторів Windows c називають виконуваний за замовчуванням "a.exe". На щастя, наскільки я можу сказати, всі вони мають однакову довжину, тому обхідний рахунок однаковий. (хоча якщо у вас немає визначеного коду, вам може знадобитися додати такий лист, як gcc, до команди компіляції, додавши 1 байт).

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



2

[EDIT]

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.