Interpretuj brainf ***


113

Napisz najkrótszy program w swoim ulubionym języku, aby zinterpretować program „ pieprzony mózg ”. Program jest odczytywany z pliku. Wejście i wyjście to standardowe wejście i standardowe wyjście.

  1. Rozmiar komórki: 8-bitowy bez znaku. Przepełnienie jest niezdefiniowane.
  2. Rozmiar tablicy: 30000 bajtów (bez kółek)
  3. Złe polecenia nie są częścią danych wejściowych
  4. Komentarze zaczynają się od # i rozciągają do końca wiersza Komentarze nie zawierają wszystkiego+-.,[]<>
  5. brak symbolu EOF

Bardzo dobry test można znaleźć tutaj . Odczytuje liczbę, a następnie drukuje liczby pierwsze do tej liczby. Aby zapobiec gniciu linków, oto kopia kodu:

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

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

Przykładowy przebieg:

$ 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
Powinieneś wyjaśnić o 1) rozmiarze pamięci 2) czy pamięć jest zakreślona 4) może jakieś inne szczegóły
Nakilon

3
Zastanawiam się, czy powinny istnieć dwie kategorie: te programy, które używają eval (lub wykonują shell do kompilacji) - i te, które tego nie robią.
MtnViewMark

34
Chciałbym zobaczyć, jak ktoś odpowiada na to w pieprzony mózg.
Hannesh

3
Co oznacza „brak symbolu EOF”? Czy wartość komórki pozostaje niezmieniona podczas próby ,EOF? Czy to od nas zależy, czy wybierzesz wartość przy ,EOF? A może zachowanie EOF jest całkowicie niezdefiniowane?
Martin Ender,

3
Podobnie, co powinno się stać, gdy ktoś spróbuje pozostawić komórki 30k po obu stronach? Czy głowica taśmy powinna pozostać na miejscu, czy jest to niezdefiniowane zachowanie?
Martin Ender

Odpowiedzi:


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

Działa bezbłędnie hello.bf i 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

Inicjalizacja: Kod operacji do tabeli translacji Perla jest przechowywany w %c. Czytelny formularz wygląda następująco:

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

Krok 1: Wprowadź dane programu Slurp $_i przekształć je w kod Perla za pomocą tabeli translacji. Komentarze są automatycznie usuwane (zastępowane przez undef) na tym etapie.

Krok 2: Rozpakuj wszystkie $b[$p]wystąpienia

Krok 3: Uruchom program za pomocą eval.


Wystarczy użyć qwskładni Perla, aby %cbezpośrednio zdefiniować - dobre dla 7 mniej znaków (musisz powiedzieć print+chr$b[$p]i ord(getc)chociaż)
mob

Liczę 18 uratowanych… dzięki! (aktualizacja za minutę)
JB

1
@olivecoder O czym ty do diabła mówisz?
JB

Tabela% c jest zadeklarowana i zdefiniowana w pierwszym wierszu; jego postacie są doskonale rozliczane.
JB

@JB hej, przypadkowo nacisnąłem głos na twoją odpowiedź i jest ona zablokowana, czy możesz to edytować, abym mógł cofnąć głosowanie?
cykloheksanol.

67

Python (bez ewaluacji), 317 bajtów

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 zaf(u,c,k)
Joel Cornett

9
To jest jeden piękny hałas, sir
globby

-1 bajt, jeśli zastąpi while b*c[c[0]]and j<1sięwhile b*c[c[0]]*(j<1)
Daniil Tutubalin

50

16-bitowy kod maszynowy 8086: 168 bajtów

Oto wersja zakodowana w standardzie base64 , przekonwertuj i zapisz jako „bf.com” i uruchom z wiersza polecenia systemu Windows: „bf progname”

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

EDYTOWAĆ

Oto jakiś asembler (w stylu A86) do stworzenia pliku wykonywalnego (musiałem to odtworzyć, ponieważ zgubiłem oryginalne źródło!)

    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

Dodałem wersję kodu źródłowego programu. Właśnie zauważyłem, że znaki spoza bf powodują, że program kończy pracę, a nie jest ignorowany. Łatwo to naprawić, a ja zostawię to jako ćwiczenie dla ludzi, którzy sami to zrobią.
Skizz

Pamiętam, że mam Linuksową wersję ELF 166 bajtów, 10 lat temu, tutaj muppetlabs.com/~breadbox/software/tiny
Emmanuel

39

pieprzenie mózgu , 843 691 bajtów

Edycja: postanowiłem ponownie to sprawdzić i znalazłem zaskakującą liczbę sposobów gry w golfa poza bajtami

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

Pobiera to dane wejściowe w postaci, w code!inputktórej !inputopcja jest opcjonalna. Symuluje także komórki ujemne bez użycia samych komórek ujemnych i może przechowywać do (30000-(length of code+6))/2komórek.

Wypróbuj online!


Aby upewnić się, że mam rację, jeśli uruchomię ten program z tym programem, mogę zagnieździć go na 5 poziomach głębokości i nadal obsługiwać kody o długości 262.
Draco18s

@ Draco18s Podejrzewam, że wcześniej zabrakło 30000 komórek, ponieważ rozmiar każdego zagnieżdżonego interpretera rośnie wykładniczo. Myślę, że dostaniesz 2, może 3 poziomy głębokości
Jo King

Nawet 3 głębokie byłyby przezabawnie głupie.
Draco18s

27

Ruby 1.8.7, 188 185 149 147 znaków

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

Nieco czytelna wersja:

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

Jak widzisz, bezwstydnie ukradłem twój pomysł na tłumaczenie na język hosta, a następnie za pomocą eval, aby go uruchomić.


Można zgolić bajt bajt w porównaniu do zera >0zamiast testowania równość: !=0. Specyfikacja mówi „bez znaku”, a przepełnienie jest niezdefiniowane.
anonimowy tchórz

3e4będzie również działać w przeciwieństwie do30000
anonimowy tchórz

@Charlie: Dzięki. Chociaż, żeby być uczciwym, nie napisałem „niepodpisany”, kiedy napisałem kod. Szczerze mówiąc, nie wiedziałem, że można napisać 3e4. To bardzo dobra uwaga i dobrze wiedzieć.
sepp2k

File.read($*.pop).bytes-> też $<.bytespowinno działać
Arnaud Le Blanc

1
Ruby 1.8.7 ma jeszcze krótszą składnię, aby zbudować dosłowny skrót: {?a,"foo"}który jest równoważny z {?a=>"foo"}. I testowanie tutaj pokazuje, że faktycznie może zastąpić File.read($*.pop).bytesz $<bez żadnych problemów. Również wstawienie wszystkiego do czegoś takiego jak eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";"skraca rozwiązanie o kolejne kilka znaków.
Ventero

26

Binary Lambda Calculus 112

Program pokazany na zrzucie szesnastkowym poniżej

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

oczekuje, że jego dane wejściowe będą składały się z programu Brainfuck (patrząc tylko na bity 0,1,4 w celu rozróżnienia między -. + <>] [), a następnie a], a następnie danych wejściowych dla programu Brainfuck.

Zapisz powyższy zrzut heksowy za pomocą xxd -r> bf.Blc

Chwyć interpreter blc z 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

Witaj świecie!


1
Dlaczego to w ogóle istnieje? Najwyraźniej istnieje nawet w dziedzinie badań . Oo
Isiah Meadows,

Więc to nie zadziała z komentowanymi programami typu „pieprzenie mózgu”?
kamoroso94

Nie, nie bez uprzedniego usunięcia komentarzy.
John Tromp

18

Retina 0.8.2 , 386 391 386 bajtów

Kod zawiera niedrukowalne 0x00znaki NUL ( ). Nie jest jeszcze super golfa, ponieważ jest już naprawdę wolny, a jeśli będę grać w golfa więcej, nie wiem, ile czasu zajmie ukończenie. Wydaje się, że upłynął limit czasu na próbce znalezienia pierwszego.

Mogą występować błędy w tłumaczu online lub w moim programie (nowe wiersze nie są wyświetlane na wyjściu?).

Przyjmuje dane wejściowe jak <code>│<input>. Nie, to nie jest potok ( |). To znak Unicode U+2502. Kod wykorzystuje również znaki Unicode ÿ▶◀├║. Znaki Unicode są używane do obsługi wprowadzania wszystkich znaków ASCII. Dlatego te znaki należy oddzielić od kodu znakiem innym niż ASCII.

Wypróbuj online

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\`.*├|║.*

Zauważ, że jest tam końcowy znak nowej linii.

Krótkie wyjaśnienie:

Zero 0x00są używane do taśmy, która jest nieskończona. Pierwsza zamiana ustawia interpreter w postaci ▶<code>│<input>├<output>║▶<tape>, w której pierwszy jest wskaźnikiem kodu, a drugi wskaźnikiem taśmy.

ÿto 0xFF(255), które jest używane do transliteracji (używanej do implementacji +i -) do zawijania komórek z powrotem do zera.

służy tylko do odczytu (w przypadku, gdy program jest zatrzymany w środku lub chcesz zobaczyć wykonanie programu w połowie). W przeciwnym razie nie można określić, w którą stronę porusza się wskaźnik.

Skomentowany kod:

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

Kliknij tutaj, aby uzyskać kod z zerami zamiast pustych bajtów. Wszelkie wystąpienia $0nie powinny być zastępowane zerami.

Edycja : teraz obsługuje puste dane wejściowe i pomija końcowe znaki nowej linii.

Nieskończone wyjście jest teraz obsługiwane. (403 bajty)


I niby szkoda że ja umieściłeś <code>, a <tape>obok siebie (choć byłoby więcej znaków) tak, że przejście do tłumacza SMBF byłoby łatwiejsze, jeśli kiedykolwiek zdecydujesz się zrobić.
mbomb007,

14

TI-BASIC, 264 bajty

Z powodu ograniczeń w TI-BASIC, to tak naprawdę nie kwalifikuje się do tego wyzwania, ponieważ łamie zasadę 2; RAM kalkulatorów jest bardzo ograniczony, a zrobienie czegoś takiego 30000->dim(L1(używam L1 do stosu / tablicy) zmusi go do rzucenia ERR:MEMORY. W związku z tym stos / tablica zaczyna się od wielkości 1 i rośnie, jeśli wskaźnik wskazuje na element poza jego końcem. Łamie także zasadę 3, ponieważ już łamie zasadę 2, więc równie dobrze mogę nie zawracać sobie głowy limitem wielkości komórki.

Nawiasem mówiąc, prawdopodobnie nadal można grać w golfa ... Wprowadziłem jedną lub dwie zmiany w tym celu od pierwszego przesłania, ale jeśli poniższa wersja nie działa, wróć do edycji od 6 maja 2015 roku i skorzystaj z niej zamiast tego kod. Ponadto, ponieważ tak naprawdę nie ma ASCII w TI-BASIC, przyjmuje dane liczbowe o dowolnej wielkości (i wszystko, co zwraca liczbę, na przykład zmienną lub wyrażenie) jako dane wejściowe, a następnie wypisuje liczby.

Użyj SourceCodera, aby wbudować go w plik .8xp, a następnie wyślij go do kalkulatora za pomocą TI-Connect lub TILP lub czegoś takiego, i uruchom go, włączając w to swój program typu „pieprzenie mózgu” w podwójnych cudzysłowach, a następnie dwukropek i dowolną nazwę programu TI-BASIC. Na przykład, jeśli nazwał ją BRAINF, można uruchomić program tak: "brainfuck goes here":prgmBRAINF. Jeśli masz powłokę na swojej Calc, który przechwytuje inne polecenia, gdy wykryje prgmznak, choć to zrobić: "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

Jeśli nie masz sposobu na podłączenie kalkulatora do komputera, a zamiast tego chcesz wpisać to na kalkulatorze (nie mogę sobie wyobrazić, dlaczego chcesz, ale dygresję) zauważ, że ->jest to STO>przycisk nad ON klucz, ~jest symbolem ujemnym obok ENTER i zastępuje wszystkie wystąpienia L<number>odpowiednim tokenem listy znalezionym na2ND -> <number on keypad>

Dzięki thomas-kwa (przynajmniej myślę, że to jego nazwa użytkownika Stack) za pomoc w optymalizacji tego, szczególnie z instrukcjami [i ].


1
Czy potrzebujesz wokół siebie parens Ans+S?
Zacharý

@ Zacharý Dobry połów, nie. Musiałem nie mieć pewności, jak działa PEMDAS, czy coś w tym rodzaju ... Powstrzymam się jednak od edytowania, ponieważ minęło tyle czasu, że zdecydowanie nie warto wysadzać tego posta z przodu i ponieważ dwubajtowy redukcja nie da odpowiedzi żadnej przewagi nad innymi lol.
MI Wright,

1
Pamiętam, jak 2-3 lata temu, kiedy użyłem tego programu do interpretacji Brainf *** na moim kalkulatorze. I, to jest pytanie zinterpretowane przez mózg ***, myślę, że powinno być na szczycie, szczerze mówiąc.
Zacharý

1
Myślę, że cała linia mogłaby być S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. ( a-a=0). I hej, nie martw się, że zapomnisz tutaj o JEDNEJ kolejności operacji, widziałem wielu ludzi, którzy zapominają o kolejności operacji dla %(mod) na wyzwaniu.
Zacharý

1
O cholera, tak. Okej, to daje co najmniej 10 bajtów mniej, ponieważ if może być również jedno-liniowy, a także kilka innych rzeczy ... może również edytować. Zmusiłeś mnie do wyciągnięcia mojego kalkulatora po raz pierwszy od roku, żeby to sprawdzić, haha
MI Wright

13

Python 275 248 255

Postanowiłam spróbować.

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
Zgrabnie, generujesz kod źródłowy Pythona za pomocą brainfuck.

1
Możesz usunąć 1 znak, „zaimportować sys jako s” i zamienić „sys” na „s” w pozostałych
TY

Zauważ, że jest to w rzeczywistości 247 znaków. (Zobacz później paskudne miejsce exec t?). Jeśli użyjesz końcówki S. Mark , a także przekształcisz cały forcykl w jedną linię, możesz zmniejszyć ją do 243 znaków.
Oleh Prypin

Nie udaje się to na żadnym wejściu zawierającym []ważny, choć trywialny program bf. Zasugerowałem edycję, która to rozwiązuje, ale zwiększa liczbę znaków. Aby jeszcze bardziej zmniejszyć liczbę znaków, możesz from sys import *i używaj 'i+=1,...'.split(',')zamiast ['i+=1',...].
stoisko

7
Chciałbym +1, ale wiele ulepszeń zostało zasugerowanych i nie zostało wdrożonych.
mbomb007

12

Haskell, 457413 znaków

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

Ten kod „kompiluje” program BF do IOdziałania w postaci State -> IO Statesuwaka na nieskończonym łańcuchu.

Smutne, że musiałem wydać 29 znaków, aby wyłączyć buforowanie. Bez nich to działa, ale nie widzisz monitów przed wpisaniem danych wejściowych. Sam kompilator ( b, fi k) ma tylko 99 znaków, środowisko wykonawcze ( #i %) ma 216. Sterownik z / stan początkowy kolejne 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 

aktualizacja 2011-02-15: Wprowadzono sugestie JB, zmieniono nieco nazwę i zaostrzonomain


1
Powinieneś być w stanie uzyskać buforowanie z just IO, a argumenty z just System(-19). Niepokoi mnie również kwestia buforowania, ponieważ specyfikacja tak naprawdę nie wspomina o tym, a najczęściej głosowana odpowiedź nawet nie I / O. Jeśli trzeba go zachować, to chyba krótsze hFlushpo każdym zapisie niż zmienić ustawienia globalne buforowania (-34 + 15).
JB

11

Przenośnik, 953

To może być najpiękniejszy kod, jaki kiedykolwiek zobaczysz:

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
Czy możesz dodać wyjaśnienie i link do implementacji? Chcę zrozumieć piękno. ;)
DLosc

1
Cóż, obecnie go rozwijam, jest kompilator i bardzo złe wyjaśnienie na github.com/loovjo/Conveyor . Źródło jest dość czytelne, jeśli chcesz je zrozumieć.
Loovjo

9

C 284 362 (z pliku)

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

Liczby pierwsze:

Liczby do: 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
Naciśnij dowolny klawisz, aby kontynuować . . .

Skompilowano i uruchomiono pomyślnie VS2008

Oryginalne rozwiązanie nie rozpoznało pętli, które początkowo były ustawione na zero. Wciąż trochę miejsca na golfa. Ale w końcu rozwiązuje program Prime Number.

Nie golfowany:

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

Testy:

Witaj świecie

Zgnilizna 13


Czy sprawdzasz ten sam wskaźnik ( l) przy każdej pętli? Myślę, że powinieneś sprawdzić bieżącą lokalizację head ( p).
Alexandru

Podaję wskaźnik do bufora i wskaźnik do strumienia. Sprawdza na końcu pętli, czy wskaźnik lw buforze osiągnął zero, i łamie się, w przeciwnym razie resetuje strumień z powrotem do oryginalnej pętli [. Jest to konieczne w przypadku zagnieżdżonych [pętli.
snmcdonald

1
Tak. Tak myślałem. Nie powinieneś sprawdzać wartości przy wskaźniku przy pierwszym wejściu do pętli, ale wartość przy bieżącym wskaźniku. Sprawdź test w pytaniu. Twój program zawiesza się.
Alexandru

1
Można zastąpić break;elseprzez return;.
Alexandru

3
Myślę, że można zastąpić (c==62)?a:bz (c-62)?b:a.
Alexandru

9

PHP 5.4, 296 294 273 263 261 209 191 183 178 166 znaków:

Dałem mu szansę bez użycia eval, ale ostatecznie musiałem go użyć

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

Wszystkie polecenia działają. To mocno nadużywa zmiennych zmiennych i wyrzuca ostrzeżenia. Jednak jeśli ktoś zmieni swoje php.ini na ostrzeżenia o squelch (lub potoki stderr na / dev / null), działa to świetnie.

Weryfikacja (przykład „Hello World!” Z Wikipedii ): http://codepad.viper-7.com/O9lYjl

Niegolfowany, 367 365 335 296 267 znaków:

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

Należy to uruchomić za pomocą wiersza polecenia: 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

Dość prosta konwersja instrukcji, a następnie Invoke-Expression.

Historia:

  • 2011-02-13 22:24 (220) Pierwsza próba.
  • 2011-02-13 22:25 (218) 3e4jest krótszy niż 30000.
  • 2011-02-13 22:28 (216) Niepotrzebne podziały linii. Dopasowywanie liczb całkowitych zamiast znaków jest krótsze.
  • 2011-02-13 22:34 (207) Użyto indeksów w tabeli skrótów zamiast switch.
  • 2011-02-13 22:40 (205) Lepszy rzut na łańcuch usuwa dwa nawiasy.
  • 2011-02-13 22:42 (204) Po sporze nie ma potrzeby wstawiania spacji Write-Host.

8

C, 333 znaków

To mój pierwszy interpreter BF i pierwszy golf, który musiałem debugować.

Działa to na generatorze liczb pierwszych w systemie Mac OS X / GCC, ale #include<string.h>może być konieczne dodatkowe, kosztem 19 dodatkowych znaków, jeśli niejawna definicja strchrnie działa na innej platformie. Zakłada również O_RDONLY == 0. Poza tym pominięcie intdeklaracji Mzapisuje 3 znaki, ale wydaje się, że nie jest to zgodne z C99. To samo z trzecim *w b().

Zależy to od szczegółów kodowania ASCII. Wszystkie operatory Brainfuck są parami komplementarnymi oddzielonymi odległością 2 w przestrzeni kodu ASCII. Każda funkcja w tym programie implementuje parę operatorów.

#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]();
}

Myślę, że można go bardziej zmniejszyć, używając notacji „e” dla wszystkich dużych liczb.
luser droog

@luser: Początkowo też byłem zaskoczony, ale język i kompilator na to nie pozwalają. Udało mi się zmniejszyć kolejne 4 znaki za pomocą #definedrobnych poprawek, a użycie zamiast tabeli funkcji byłoby również bardziej przydatne. Podoba mi się numer 333 i tabela: v).
Potatoswatter

Och, racja. Naprawdę powinienem to wiedzieć. Notacja elektroniczna jest wytwarzana dla stałej zmiennoprzecinkowej, podczas gdy deklaracja wymaga liczby całkowitej. BTW, to może być oszustwo, ale sprawdź wersję nieko.net/projects/brainfuck dla wersji Urban Müller. Największym zyskiem wydaje się być duże wykorzystanie ||.
luser droog

8

CJam, 75 bajtów

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

Wypróbuj online: odwracacz strun , Hello World .

Wyjaśnienie

Pobiera kod w pierwszym wierszu STDIN i wprowadza wszystkie wiersze poniżej.

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.

Co z tą magiczną listą?

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

Wynikowa lista jest następująca:

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)

Generujemy fragmenty dla +i >od tych dla -i <, po prostu zmieniając lewe pareny („dekrementacja” CJam) na prawe parens („inkrement” CJam).


Najkrótsza odpowiedź i największy zwycięzca
Jack Giffin

7

F #: 489 znaków

Poniższy program nie przeskakuje do instrukcji „[” / „]”, ale skanuje kod źródłowy w poszukiwaniu następnego pasującego tokena. To oczywiście spowalnia, ale wciąż może znajdować liczby pierwsze poniżej 100. Typy liczb całkowitych F # nie przepełniają się, ale zawijają.

Oto krótka wersja:

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

Paskudne gotcha było to, że program primes.bf dusi się na nowej linii Windows. Aby go uruchomić, musiałem zapisać numer wejściowy w formacie tekstowym w formacie UNIX i podać go do programu za pomocą potoku:

interpret.exe prime.bf < number.txt

Edycja: wprowadzenie Alt + 010, a następnie Enter również działa w Windows cmd.exe

Oto dłuższa wersja:

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

Rozwiązałem problem Enter, nie naciskając go, ale Ctrl + J :-)
Joey

Ctrl + J nie działał dla mnie, ale wpisanie Alt + 010, a następnie Enter.
cfern

7

Delfy, 397 382 378 371 366 364 328 znaków

Zjedz to 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.

Tutaj ten sam kod, wcięty i skomentowany:

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.

Ten zajął mi kilka godzin, ponieważ nie jest to typ kodu, który zwykle piszę, ale baw się dobrze!

Uwaga: Test główny działa, ale nie kończy się na 100, ponieważ czyta # 13 (CR) przed # 10 (LF) ... czy inne zgłoszenia również mają ten problem, gdy działają na systemach operacyjnych CRLF?


Łał! Nigdy nie spodziewałbym się, że zwyciężę C w zwięzłości z Delphi! Dopóki nie zastosujesz moich pomysłów do zgadywania CI ;-)
PatrickvL,

7

C, 260 + 23 = 283 bajtów

Stworzyłem program C, który można znaleźć tutaj .

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

Musi zostać skompilowany za pomocą gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.ci może być wywoływany w następujący sposób: w pmmbf ",[.-]" 30000którym pierwszy argument (cytowany) zawiera program bf do uruchomienia, drugi określa, jak duża powinna być taśma.


1
Myślę, że musisz dodać 23 znaki do tej -D"q(a,b)"="*c-a||(b);"opcji, ponieważ wydaje mi się to (przynajmniej w moim ograniczonym rozumieniu), aby pomóc ci zmniejszyć kod.
Gareth,

Opcja jest zawarta w opublikowanym tekście. Powodem tego jest unikanie długiego słowa definei nowej linii, ale nie sądzę, że to naprawdę koszerne. W każdym razie z cytatami, komentarzami i gcc -Dwcale nie widzę przewagi.
Potatoswatter

5

C 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);}

Uruchom jako ./a.out primes.bf

Wersja bez golfa:

#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

Przyznaję, że poddałem recyklingowi mój stary program (ale musiałem go nieco zmienić, ponieważ stara wersja nie miała danych wejściowych, ale sprawdzanie błędów ...).

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

Działa poprawnie kalkulator liczb pierwszych.

Widzę teraz, że Alexandru ma odpowiedź, która ma pewne podobieństwa. I tak opublikuję wiele odpowiedzi, ponieważ myślę, że są w tym nowe pomysły.


5

C (gcc) Linux x86_64, 884 621 525 487 439 383 358 354 bajtów

*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);}

Wypróbuj online!

Jest to JIT, który kompiluje kod BF do języka maszynowego x86_64 w czasie wykonywania. Wykonuje tłumaczenia prostą tak powszechnie występujące sekwencje, takie jak >>>, <<<, +++i ---nie są coalesced do szybszych instrukcji.

Wersja mniej golfowa:

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

C 374 368

Czyta z pliku. Przechodzi test PRIME.BF.

Zastosowanie: ./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;}}


Przeformatowany:

#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 vs 30000. Twój bufor jest za mały. Rozmiar programu jest również zbyt mały.
Alexandru

Zrobiłem literówkę, naprawiłem. Co rozumiesz przez rozmiar programu? Jeśli masz na myśli maksymalny rozmiar pliku, nie określiłeś minimalnego rozmiaru, który powinien obsługiwać.
jtjacques

4

Lua, 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]"))()

Nieco czytelna wersja:

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

Działa świetnie

Lua, 478, bez obciążania

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

Wersja do odczytu:

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 bajtów

Zajęło to trochę czasu. Grałem w interpretera Brainfuck przez ... nie mnie.

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

4

Przypomnijmy , 594 bajty

W skrócie: Recall nie ma operatorów arytmetycznych w klasycznym sensie, ma jedynie operacje bitowe. Nie możesz po prostu „dodać” itp. Recall jest również ściśle oparty na stosach.

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

Przykład 1: Wydrukuj coś

Wejście:

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

Wynik:

PPCG rocks!

Przykład 2: Wyprowadzanie liczb kwadratowych do 100

Wejście:

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

Wynik:

0
1
4
9
16
25
36
49
64
81
100

Ten przykład może potrwać kilka minut i może spowodować komunikat „ta karta jest zawieszona”. Zignoruj ​​to i poczekaj.


4
Twoja domena witryny wygasła. Również ta odpowiedź nie jest konkurencyjna, ponieważ język jest nowszy niż wyzwanie.
mbomb007

3

OCaml (lex), 497 znaków

OCamllex jest częścią standardowej dystrybucji 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}

Zapisz jako b.mll i uruchom z

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

Nie lubię parsowania ręcznie, więc użyłem dostarczonego generatora leksykalnego. Z odczytanych tokenów tworzymy funkcję dla całego programu brainf * ck.


3

C # (2861 znaków, ~ 84 linii)

To nie jest najładniejsze rozwiązanie problemu i prawdopodobnie nie wszystko z tego „golfa”, ponieważ nie martwiłem się tak długo, jak powinienem być. (Nie usunąłem komentarzy ani dodatkowej białej spacji). Chciałem tylko spróbować czegoś w nowym języku, aby zobaczyć, czy mogę. Gdybym to zrobił ponownie, porzuciłbym użycie stosu do powrotu z „]” i po prostu spojrzałem wstecz. Uruchom bez argumentów wiersza poleceń, uruchamia program hello world podany w opisie problemu. Akceptuje jeden argument wiersza poleceń, nazwę pliku programu do uruchomienia.

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

        }
    }

}

Edycja: Usunięto nieużywane odwołania.


1
@ mbomb007 - zaktualizowano. Zupełnie zapomniałem, że nawet to zrobiłem. (Nawet nie zdawałem sobie sprawy, że ktoś nawet czytał te stare pytania)
2015

Ludzie nie tylko je czytają, ale także odpowiadają i golfa.
mbomb007,

3

C (gcc) , 273 268 bajtów

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

Wypróbuj online!

-5 dzięki pułapce cat

Pobiera dane wejściowe ze standardowego wejścia.

To trochę zależy od środowiska, ale jest dość spójne. Jest to efektywne rozwiązanie dla c. Zapisuje odpowiedni program C do pliku wc, kompiluje go i uruchamia jako żądany plik wykonywalny. Zatem jako efekt bonusowy faktycznie kompiluje kod bf i pozostawia go a.outjako plik binarny. Pamiętaj, że w zależności od systemu może być konieczna modyfikacja ostatniego ciągu. W szczególności większość kompilatorów systemu Windows c nazywa domyślny plik wykonywalny „a.exe”. Na szczęście, o ile mi wiadomo, wszystkie mają tę samą długość, więc liczba bajtów jest taka sama. (chociaż jeśli nie masz zdefiniowanego cc, może być konieczne dodanie litery takiej jak gcc do polecenia kompilacji, dodanie 1 bajtu).

Wiem, że ten wątek jest trochę stary, ale nie widziałem jeszcze tego stylu rozwiązania C, więc pomyślałem, że go dodam.



2

[EDYTOWAĆ]

C ++ 11, 355, czyta z pliku:

#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]();
}

Test

http://ideone.com/b7vO4

[STARA WERSJA]

C ++ 11, 391, aby zobaczyć: 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]();
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.