Interpretazione del cervello ***


113

Scrivi il programma più breve nella tua lingua preferita per interpretare un programma brainfuck . Il programma viene letto da un file. Input e output sono input standard e output standard.

  1. Dimensione cellulare: 8 bit senza segno. L'overflow non è definito.
  2. Dimensione array: 30000 byte (non cerchiato)
  3. I comandi errati non fanno parte dell'input
  4. I commenti iniziano con # e si estendono fino alla fine della riga I commenti non sono tutti presenti+-.,[]<>
  5. nessun simbolo EOF

Un ottimo test può essere trovato qui . Legge un numero e quindi stampa i numeri primi fino a quel numero. Per prevenire la putrefazione dei link, ecco una copia del codice:

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

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

Esempio di esecuzione:

$ 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
Dovresti chiarire circa 1) dimensione della memoria 2) la memoria è cerchiata 4) forse altri dettagli
Nakilon,

3
Mi chiedo se ci dovrebbero essere due categorie: quei programmi che usano eval (o shell out per compilare) - e quelli che non lo fanno.
MtnViewMark,

34
Mi piacerebbe vedere qualcuno rispondere a questo in Brainfuck.
Hannesh,

3
Cosa significa "nessun simbolo EOF"? Che il valore della cella rimanga invariato quando si prova ,su EOF? O sta a noi scegliere un valore quando ,proviamo su EOF? O il comportamento indefinito dell'EOF è del tutto?
Martin Ender,

3
Allo stesso modo, cosa dovrebbe succedere quando qualcuno cerca di lasciare le celle da 30k su entrambi i lati? La testina del nastro deve rimanere in posizione o questo comportamento indefinito?
Martin Ender,

Risposte:


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

Questo funziona perfettamente hello.bf e 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

Inizializzazione: viene memorizzato il codice operativo nella tabella di traduzione Perl %c. Il modulo leggibile è simile al seguente:

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

Passaggio 1: immettere il programma Slurp in $_e trasformarlo in codice Perl usando la tabella di traduzione. I commenti vengono automaticamente rimossi (sostituiti con undef) in questo passaggio.

Passaggio 2: decomprimere tutte le $b[$p]occorrenze

Passaggio 3: avviare il programma utilizzando eval.


Basta usare la qwsintassi di Perl per definire %cdirettamente - buono per 7 caratteri in meno (dovrete dire print+chr$b[$p]e ord(getc), comunque)
mob

Conto 18 salvati ... grazie! (aggiornamento in un minuto)
JB

1
@olivecoder Di cosa stai parlando?
JB

La tabella% c è dichiarata e definita nella prima riga; i suoi personaggi sono perfettamente spiegati.
JB

@JB hey, ho premuto per errore il voto sulla tua risposta ed è bloccato, puoi modificarlo in modo da poter annullare il voto verso il basso?
Cicloesanolo.

67

Python (no eval), 317 byte

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

9
È un bel rumore, signore
lugubre il

-1 byte se si sostituisce while b*c[c[0]]and j<1conwhile b*c[c[0]]*(j<1)
Daniil Tutubalin

50

Codice macchina 8086 a 16 bit: 168 byte

Ecco la versione codificata base64 , converti e salva come 'bf.com' ed esegui dal prompt dei comandi di Windows: 'bf progname'

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

MODIFICARE

Ecco un assemblatore (stile A86) per creare l'eseguibile (ho dovuto decodificare questo dato che avevo smarrito la fonte originale!)

    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

Ho aggiunto una versione del codice sorgente del programma. Ho appena notato che i caratteri non bf causano la chiusura del programma anziché essere ignorati. Facile da risolvere e lo lascerò come un esercizio per le persone a farlo da soli.
Skizz

Ricordo di aver ottenuto la versione ELF di Linux 166 byte, 10 anni fa, qui muppetlabs.com/~breadbox/software/tiny
Emmanuel,

39

brainfuck , 843 691 byte

Modifica: ha deciso di rivisitare questo e ha trovato un numero sorprendente di modi per golfare byte

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

Ciò accetta input nel formato in code!inputcui !inputè facoltativo. Simula anche le cellule negative senza utilizzare le stesse cellule negative e può memorizzare fino a (30000-(length of code+6))/2celle.

Provalo online!


Solo per essere sicuro di aver capito bene, se avessi eseguito questo programma con questo programma, avrei potuto annidarlo a 5 livelli di profondità e gestire ancora input di codice della lunghezza 262.
Draco18s

@ Draco18s Sospetto che prima avresti esaurito le 30000 celle, poiché le dimensioni di ciascun interprete nidificato aumentano in modo esponenziale. Penso che otterrai 2, forse 3 livelli di profondità
Jo King,

Anche 3 in profondità sarebbe esilarantemente sciocco.
Draco18s

27

Ruby 1.8.7, 188 185 149 147 caratteri

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

Versione un po 'leggibile:

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

Come vedi, ho spudoratamente rubato la tua idea di tradurre nella lingua host e quindi usare eval per eseguirla.


È possibile radere un byte di byte a confronto a zero >0piuttosto che testare l'uguaglianza: !=0. Le specifiche dicono unsigned e overflow non è definito.
codardo anonimo il

3e4funzionerà anche al contrario30000
codardo anonimo il

@Charlie: grazie. Anche se per essere onesti non ha detto "unsigned" quando ho scritto il codice. Onestamente non sapevo che avresti potuto scrivere 3e4. Questo è un punto molto buono e buono a sapersi.
sepp2k,

File.read($*.pop).bytes-> $<.bytesdovrebbe funzionare anche
Arnaud Le Blanc,

1
Ruby 1.8.7 ha una sintassi ancora più breve per creare un hash letterale:, {?a,"foo"}che equivale a {?a=>"foo"}. E test qui dimostra che in realtà si può sostituire File.read($*.pop).bytescon $<senza problemi. Inoltre, integrare tutto in qualcosa di simile eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";"accorcia la soluzione di altri pochi personaggi.
Ventero,

26

Calcolo lambda binario 112

Il programma mostrato nella discarica esadecimale di seguito

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

si aspetta che il suo input sia costituito da un programma Brainfuck (guardando solo i bit 0,1,4 per distinguere tra, -. + <>] [) seguito da a], seguito dall'input per il programma Brainfuck.

Salvare il dump esadecimale sopra con xxd -r> bf.Blc

Prendi un interprete blc da 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

Ciao mondo!


1
Perché esiste questo? Apparentemente, esiste persino nel regno della ricerca . Oo
Isiah Meadows il

Quindi questo non funzionerebbe con i programmi brainfuck commentati?
kamoroso94,

No, non senza prima eliminare i commenti.
John Tromp,

18

Retina 0.8.2 , 386 391 386 byte

Il codice contiene 0x00caratteri NUL ( ) non stampabili . Inoltre, non è ancora super golf, perché è già molto lento e se gioco più, non so quanto tempo ci vorrebbe per finire. Appare in timeout sul campione di ricerca primaria.

Potrebbero esserci dei bug nell'interprete online o nel mio programma (le nuove righe iniziali non vengono visualizzate nell'output?).

Accetta input come <code>│<input>. No, questo non è un pipe ( |). È il personaggio Unicode U+2502. Il codice utilizza anche i caratteri Unicode ÿ▶◀├║. I caratteri Unicode vengono utilizzati per supportare l'input di tutti i caratteri ASCII. Pertanto, questi caratteri devono essere separati dal codice da un carattere non ASCII.

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

Nota che c'è una nuova riga finale lì.

Breve spiegazione:

Gli zeri 0x00vengono utilizzati per il nastro, che è infinito. La prima sostituzione imposta l'interprete nel modulo ▶<code>│<input>├<output>║▶<tape>, dove il primo è il puntatore per il codice e il secondo è il puntatore per il nastro.

ÿis 0xFF(255), utilizzato per Transliteration (utilizzato per implementare +e -) per riportare le celle a zero.

viene utilizzato solo per la leggibilità (nel caso in cui il programma venga arrestato nel mezzo o si desideri vedere il programma durante l'esecuzione). Altrimenti, non si può dire da che parte si sta muovendo il puntatore.

Codice commentato:

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

Fare clic qui per il codice con zeri al posto di byte null. Eventuali occorrenze di $0non devono essere sostituite con valori null.

Modifica : ora supporta input vuoti e elimina la nuova riga finale.

L'output infinito è ora supportato. (403 byte)


Vorrei che avessi messo l'uno <code>e l' <tape>altro uno accanto all'altro (anche se sarebbero stati più personaggi) in modo che il passaggio a un interprete SMBF sarebbe più semplice, se mai decidessi di farlo.
mbomb007,

14

TI-BASIC, 264 byte

A causa delle limitazioni in TI-BASIC, questo in realtà non è idoneo per questa sfida poiché infrange la regola 2; la RAM dei calcolatori è molto limitata e fare qualcosa del tipo 30000->dim(L1(uso L1 per lo stack / array) lo costringerà a lanciare un ERR:MEMORY. Come tale, lo stack / array inizia con una dimensione di 1 e cresce se il puntatore punta a un elemento oltre la fine di esso. Inoltre infrange la regola 3, perché sta già infrangendo la regola 2, quindi potrei anche non preoccuparmi di un limite di dimensioni delle celle.

Probabilmente potremmo ancora giocare a golf, a proposito ... Ho fatto una o due modifiche a tale scopo dal primo invio, ma se la versione seguente non funziona, torna alla modifica dal 6 maggio 15 e usa quella codice invece. Inoltre, poiché in TI-BASIC non esiste davvero ASCII, questo accetta numeri di qualsiasi dimensione (e tutto ciò che restituisce un numero, come una variabile o un'espressione) come input e genera numeri a sua volta.

Usa SourceCoder per crearlo in un file .8xp, quindi invialo alla tua calcolatrice con TI-Connect o TILP o qualcosa del genere, ed eseguilo includendo il tuo programma brainfuck tra virgolette seguito da due punti e da qualsiasi punto tu abbia chiamato il programma TI-BASIC. Ad esempio, se hai nominato è Brainf, che ci si esegue un programma come questo: "brainfuck goes here":prgmBRAINF. Se si dispone di una shell sul vostro calc che intercetta altri comandi quando rileva il prgmmotivo, però, fare questo: "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

Se non hai modo di connettere la tua calcolatrice al tuo computer e vuoi invece digitare questo su-calc (non riesco a immaginare il motivo per cui lo vorresti, ma sto divagando) nota che ->è il STO>pulsante sopra ON chiave, ~è il simbolo negativo accanto a INVIO e per sostituire tutte le istanze di L<number>con il token di elenco corrispondente trovato su2ND -> <number on keypad>

Grazie a Thomas-Kwa (almeno, penso che sia il suo nome utente Stack) per avermi aiutato a ottimizzare questo, specialmente con le istruzioni [e ].


1
Hai bisogno dei genitori in giro Ans+S?
Zacharý,

@ Zacharý Buona cattura, no. Devo essere stato incerto su come funziona PEMDAS o qualcosa del genere ... Mi asterrò dal modificare, tuttavia, perché è passato così tanto tempo che sicuramente non vale la pena di mettere questo post in primo piano e perché un due byte la riduzione non darà alla risposta alcun tipo di vantaggio rispetto agli altri lol.
MI Wright,

1
Ricordo come 2-3 anni fa quando ho usato questo programma per interpretare Brainf *** sulla mia calcolatrice. Ed è una domanda interpretata da brainf ***, penso che dovrebbe essere al top per essere onesti.
Zacharý,

1
In realtà, penso che l'intera linea potrebbe essere S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. ( a-a=0). E hey, non preoccuparti di dimenticare UN ordine delle operazioni qui, ho visto un sacco di persone dimenticare l'ordine delle operazioni per %(mod) in una sfida.
Zacharý,

1
Oh dang, sì. Va bene, questo dà almeno 10 byte di sconto dal momento che l'if può essere fatto anche come una linea, oltre ad altre cose ... può anche modificare, quindi. Mi hai costretto a tirare fuori la mia calcolatrice per la prima volta dopo circa un anno per controllare queste cose, haha
MI Wright,

13

Pitone 275 248 255

Ho deciso di provarlo.

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
Bene, stai generando il codice sorgente di Python usando Brainfuck.

1
Puoi rimuovere 1 carattere, "importa sys come s" e sostituire "sys" a "s" nel resto
TU

Si noti che si tratta in realtà di 247 caratteri. (Vedi lo spazio cattivo dopo exec t?). Se usi il suggerimento di S.Mark e fai anche l'intero forciclo in una riga, puoi ridurlo a 243 caratteri.
Oleh Prypin

Questo fallisce su qualsiasi input contenente [], un programma bf valido ma banale. Ho suggerito una modifica che risolve questo problema, ma aumenta il conteggio dei personaggi. Per ridurre ulteriormente il conteggio dei personaggi, puoi from sys import *e utilizzare 'i+=1,...'.split(',')invece di ['i+=1',...].
stand dal

7
Vorrei +1, ma molti miglioramenti sono stati suggeriti e non implementati.
mbomb007,

12

Haskell, 457 413 caratteri

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

Questo codice "compila" il programma BF in IOun'azione del modulo State -> IO Statelo stato è una cerniera su una stringa infinita.

Triste che ho dovuto spendere 29 caratteri per disattivare il buffering. Senza quelli, funziona, ma non vedi le istruzioni prima di dover digitare input. Il compilatore stesso ( b, f, e k) è a soli 99 caratteri, il runtime ( #e %) è 216. Il conducente w / stato iniziale un altro 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 

aggiornamento 15/02/2011: i suggerimenti di JB incorporati, un po 'rinominati e rafforzatimain


1
Dovresti essere in grado di ottenere il buffering da just IOe gli argomenti da just System(-19). Anche il problema del buffering mi dà fastidio, dato che le specifiche non lo menzionano davvero e la risposta più votata non fa nemmeno I / O. Se devi mantenerlo, è probabilmente più breve hFlushdopo ogni scrittura che cambiare la modalità di buffering globale (-34 + 15).
JB,

11

Trasportatore, 953

Questo potrebbe essere il codice più bello che tu abbia mai visto:

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
Potresti aggiungere una spiegazione e un link a un'implementazione? Voglio capire la bellezza. ;)
DLosc,

1
Bene, lo sto attualmente sviluppando, c'è un compilatore e una pessima spiegazione su github.com/loovjo/Conveyor . La fonte è piuttosto leggibile se vuoi capirla.
Loovjo,

9

C 284 362 (da un file)

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

Primes:

Prime fino a: 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
Premere un tasto qualsiasi per continuare . . .

Compilato ed eseguito con successo VS2008

La soluzione originale non è riuscita a riconoscere i loop inizialmente impostati su zero. Ancora spazio per il golf. Ma finalmente risolve il programma Prime Number.

Ungolfed:

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

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

test:

Ciao mondo

Rot13


Stai controllando lo stesso puntatore ( l) ogni volta che esegui il loop? Penso che dovresti controllare la posizione corrente della testa ( p).
Alexandru,

Passo il puntatore al buffer e il puntatore al flusso. Controlla alla fine del ciclo per vedere se il puntatore lnel buffer ha raggiunto lo zero e si interrompe altrimenti reimposta il flusso sul ciclo originale [. Ciò è necessario per i [loop nidificati .
Snmcdonald,

1
Si. Così ho pensato. Non si dovrebbe controllare il valore sul puntatore all'inizio immettere nel ciclo, ma il valore sul puntatore corrente. Controlla il test nella domanda. Il tuo programma si blocca.
Alexandru,

1
Puoi sostituirlo break;elsecon return;.
Alexandru,

3
Penso che puoi sostituirlo (c==62)?a:bcon (c-62)?b:a.
Alexandru,

9

PHP 5.4, 296 294 273 263 261 209 191 183 178 166 caratteri:

Gli ho dato un colpo senza usare eval, ma alla fine ho dovuto usarlo

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

Tutti i comandi funzionano. Ciò abusa pesantemente delle variabili variabili e genera avvertimenti. Tuttavia, se si cambia php.ini in avvertimenti di squelch (o pipe stderr in / dev / null), questo funziona alla grande.

Verifica (è l'esempio "Hello World!" Da Wikipedia ): http://codepad.viper-7.com/O9lYjl

Ungolfed, 367 365 335 296 267 caratteri:

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

Questo dovrebbe essere eseguito tramite la riga di comando: 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

Conversione abbastanza semplice delle istruzioni e poi Invoke-Expression.

Storia:

  • 13/02/2011 22:24 (220) Primo tentativo.
  • 13/02/2011 22:25 (218) 3e4è più corto di 30000.
  • 13/02/2011 22:28 (216) Interruzioni di riga non necessarie. La corrispondenza su numeri interi anziché su caratteri è più breve.
  • 13/02/2011 22:34 (207) Indici usati in una tabella hash anziché in switch.
  • 13/02/2011 22:40 (205) Un migliore cast su stringa rimuove due parentesi.
  • 13/02/2011 22:42 (204) Non è necessario uno spazio dopo l'argomento Write-Host.

8

C, 333 caratteri

Questo è il mio primo interprete BF e il primo golf a cui ho dovuto eseguire il debug.

Questo esegue il generatore di numeri primi su Mac OS X / GCC, ma #include<string.h>potrebbe essere necessario un ulteriore al costo di altri 19 caratteri se la definizione implicita di strchrnon dovesse funzionare su un'altra piattaforma. Inoltre, presuppone O_RDONLY == 0. A parte questo, tralasciando intla dichiarazione di Msalva 3 caratteri, ma ciò non sembra essere conforme a C99. Lo stesso con il terzo *in b().

Questo dipende dai dettagli della codifica ASCII. Gli operatori Brainfuck sono tutte coppie complementari separate da una distanza di 2 nello spazio di codice ASCII. Ogni funzione in questo programma implementa una coppia di operatori.

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

Penso che puoi ridurlo di più usando la notazione 'e' per tutti i numeri grandi.
Luser droog

@luser: inizialmente ero anche sorpreso, ma il linguaggio e il compilatore non lo permetteranno. Sono riuscito a ridurre altri 4 caratteri con modifiche, e #defineprobabilmente anche usare una tabella delle funzioni invece sarebbe più terser. Mi piace solo il numero 333 e la tabella: v).
Potatoswatter,

Oh giusto. Avrei dovuto saperlo davvero. La notazione elettronica è in produzione per una costante a virgola mobile, mentre una dichiarazione richiede un numero intero. A proposito, questo potrebbe essere un imbroglio, ma controlla nieko.net/projects/brainfuck per la versione di Urban Müller. Il maggior guadagno sembra essere un uso pesante di ||.
Luser droog

8

CJam, 75 byte

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

Provalo online: inversore di corde , Hello World .

Spiegazione

Prende il codice sulla prima riga di STDIN e immette su tutte le righe sottostanti.

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.

E quella lista magica?

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

L'elenco risultante è il seguente:

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)

Generiamo gli snippet per +e >da quelli per -e <, semplicemente cambiando le parentesi sinistre ("decremento" di CJam) in parentesi giuste ("incremento" di CJam).


Risposta più breve e il più grande vincitore
Jack Giffin,

7

F #: 489 caratteri

Il seguente programma non passa alle istruzioni '[' / ']', ma scansiona il codice sorgente per il prossimo token corrispondente. Questo ovviamente lo rende un po 'lento, ma può ancora trovare i numeri primi sotto 100. I tipi interi F # non traboccano ma si avvolgono.

Ecco la versione breve:

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

Un brutto problema era che il programma primes.bf si strozzava con le righe di Windows. Per eseguirlo ho dovuto salvare il numero di input in un documento di testo formattato UNIX e inviarlo al programma con una pipe:

interpret.exe prime.bf < number.txt

Modifica: inserendo Alt + 010 seguito da Invio funziona anche in Windows cmd.exe

Ecco la versione più lunga:

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

Ho risolto il problema di Invio non premendo ma Ctrl + J :-)
Joey

Ctrl + J non ha funzionato per me, ma digitando Alt + 010 seguito da Enter ha fatto.
cfern,

7

Delphi, 397 382 378 371 366 364 328 caratteri

Mangia questo 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.

Qui lo stesso codice, rientrato e commentato:

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.

Questo mi ha richiesto alcune ore, poiché non è il tipo di codice che scrivo normalmente, ma mi diverto!

Nota: il test primo funziona, ma non si ferma a 100, perché legge # 13 (CR) prima di # 10 (LF) ... Anche altri invii presentano questo problema quando vengono eseguiti su sistemi operativi CRLF?


Wow! Non mi sarei mai aspettato di battere C in terseness con Delphi! Non fino a quando non applicherai le mie idee
all'ipotesi

7

C, 260 + 23 = 283 byte

Ho creato un programma C che può essere trovato qui .

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

Deve essere compilato tramite gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.ce può essere chiamato come segue: pmmbf ",[.-]" 30000per cui il primo argomento (citato) contiene il programma bf da eseguire, il secondo determina la dimensione del nastro.


1
Penso che sia necessario aggiungere 23 caratteri al conteggio per l' -D"q(a,b)"="*c-a||(b);"opzione, poiché questo (almeno per mia comprensione limitata) sembra aiutarti a ridurre il codice.
Gareth,

L'opzione è inclusa nel testo pubblicato. Il motivo è evitare la parola lunga definee la nuova riga, ma non penso che sia davvero kasher. Comunque con le virgolette, i commenti e gcc -Dnon ne vedo affatto il vantaggio.
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);}

Esegui come ./a.out primes.bf

Versione Ungolfed:

#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

Ammetto di aver riciclato un mio vecchio programma (ma ho dovuto cambiarlo un po ', perché la vecchia versione non aveva input, ma il controllo degli errori ...).

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

Esegue bene il calcolatore dei numeri primi.

Vedo ora che Alexandru ha una risposta che ha alcune somiglianze. Pubblicherò comunque la mia risposta, perché penso che ci siano alcune nuove idee in esso.


5

C (gcc) Linux x86_64, 884 621 525 487 439 383 358 354 byte

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

Provalo online!

Questo è un JIT che compila il codice BF nel linguaggio macchina x86_64 in fase di esecuzione. Questo esegue una traduzione dritto in modo che si verificano comunemente sequenze come >>>, <<<, +++e ---non sono fusero in istruzioni più veloci.

Versione meno giocata a golf:

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

Legge da un file. Supera il test PRIME.BF.

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


riformattato:

#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. Il buffer è troppo piccolo. Anche la dimensione del programma è troppo piccola.
Alexandru,

Ho fatto un refuso, riparato. Cosa intendi per dimensione del programma? Se intendi la dimensione massima del file, non hai specificato un minimo che dovrebbe gestire.
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]"))()

Versione un po 'leggibile:

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

Funziona perfettamente

Lua, 478, senza loadstring

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

Versione leggibile:

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 byte

Bene, ci è voluto un po '. Ho giocato a golf con un interprete di Brainfuck da ... non da me.

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

4

Richiama , 594 byte

In breve: il richiamo non ha operatori aritmetici in senso classico, ha solo operazioni bit per bit. Non puoi semplicemente "aggiungerne uno" ecc. Il richiamo è anche strettamente basato sullo stack.

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

Esempio 1: stampa qualcosa

Ingresso:

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

Produzione:

PPCG rocks!

Esempio 2: uscita numeri quadrati fino a 100

Ingresso:

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

Produzione:

0
1
4
9
16
25
36
49
64
81
100

L'esecuzione di questo esempio potrebbe richiedere alcuni minuti e potrebbe causare un messaggio "questa scheda è bloccata". Ignoralo e aspetta.


4
Il dominio del tuo sito Web è scaduto. Inoltre, questa risposta non è competitiva, perché la lingua è più recente della sfida.
mbomb007,

3

OCaml (lex), 497 caratteri

OCamllex fa parte della distribuzione standard di 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}

Salva come b.mll ed esegui con

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

Non mi piace analizzare a mano, quindi ho usato il generatore di lexer in dotazione. Dai token letti, componiamo una funzione per l'intero programma brainf * ck.


3

C # (2861 caratteri, ~ 84 righe)

Questa non è la soluzione più carina al problema, e probabilmente non è tutto quel "golf-ish", dato che non ero tanto interessato alla lunghezza come avrei dovuto. (Non ho rimosso i commenti o lo spazio bianco extra.) Volevo solo provare qualcosa in una nuova lingua, per vedere se potevo. Se lo facessi di nuovo, lascerei cadere lo stack per tornare da ']' e guarderei indietro. Esegui senza argomenti della riga di comando, esegue il programma Hello World indicato nella descrizione del problema. Accetta un argomento della riga di comando, il nome file del programma da eseguire.

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

        }
    }

}

Modifica: rimossi riferimenti inutilizzati.


1
@ mbomb007 - Aggiornato. Ho completamente dimenticato di averlo fatto. (Non
avevo

Le persone non solo le leggono ancora, ma rispondono e le giocano a golf.
mbomb007,

3

C (gcc) , 273 268 byte

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

Provalo online!

-5 grazie a ceilingcat

Riceve input dallo stdin.

Questo si basa un po 'sull'ambiente, ma è piuttosto coerente. Questa è effettivamente la soluzione eval per c. Scrive un programma C appropriato nel file wc, lo compila e lo esegue come eseguibile desiderato. Quindi come effetto bonus questo in realtà compila il codice bf e lo lascia a.outcome binario. Si noti che a seconda del sistema potrebbe essere necessario modificare l'ultima stringa. In particolare la maggior parte dei compilatori di Windows c chiama l'eseguibile predefinito "a.exe". Fortunatamente, per quanto ne so, hanno tutti la stessa lunghezza, quindi il conto alla rovescia è lo stesso. (anche se se non hai definito un cc potresti dover aggiungere una lettera come gcc al comando di compilazione, aggiungendo 1 byte).

Sono consapevole che questo thread è un po 'vecchio, ma non ho ancora visto questo stile di soluzione C, quindi ho pensato di aggiungerlo.



2

[MODIFICARE]

C ++ 11, 355, legge dal file:

#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

[VECCHIA VERSIONE]

C ++ 11, 391, per vedere in esecuzione: 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]();
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.