Interpretar brainf ***


113

Escribe el programa más corto en tu idioma favorito para interpretar un programa de brainfuck . El programa se lee desde un archivo. Entrada y salida son entrada estándar y salida estándar.

  1. Tamaño de celda: 8 bits sin firmar. El desbordamiento no está definido.
  2. Tamaño de matriz: 30000 bytes (sin círculo)
  3. Los comandos incorrectos no son parte de la entrada
  4. Los comentarios comienzan con # y se extienden hasta el final de la línea. Los comentarios son todo lo que no está en+-.,[]<>
  5. sin símbolo EOF

Una muy buena prueba se puede encontrar aquí . Lee un número y luego imprime los números primos hasta ese número. Para evitar la descomposición del enlace, aquí hay una copia del código:

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

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

Ejemplo de ejecución:

$ 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 

55
Debe aclarar sobre 1) el tamaño de la memoria 2) es un círculo de memoria 4) tal vez cualquier otro detalle
Nakilon

3
Me pregunto si debería haber dos categorías: los programas que usan eval (o la shell para compilar) y los que no.
MtnViewMark

34
Me encantaría ver a alguien responder esto en un ataque de cerebro.
Hannesh

3
¿Qué significa "sin símbolo EOF"? ¿Que el valor de la celda no se modifica al probar ,EOF? ¿O que depende de nosotros elegir un valor al probar ,EOF? ¿O es EOF un comportamiento indefinido por completo?
Martin Ender

3
Del mismo modo, ¿qué debería suceder cuando alguien intenta dejar las células de 30k a ambos lados? ¿El cabezal de la cinta debe permanecer en su lugar o se trata de un comportamiento indefinido?
Martin Ender

Respuestas:


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

Esto ejecuta hello.bf y primes.bf sin problemas:

$ 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

Inicialización: la tabla de traducción de código de operación a Perl se almacena en %c. La forma legible se ve así:

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

Paso 1: sorber la entrada del programa $_y transformarla en código Perl usando la tabla de traducción. Los comentarios se eliminan automáticamente (se reemplazan por undef) en este paso.

Paso 2: descomprima todas las $b[$p]ocurrencias

Paso 3: Inicia el programa usando eval.


Solo use la qwsintaxis de Perl para definir %cdirectamente - bueno para 7 caracteres menos (tendrá que decir print+chr$b[$p]y ord(getc), sin embargo)
mafia

Cuento 18 guardados ... ¡gracias! (actualización en un minuto)
JB

1
@olivecoder ¿De qué demonios estás hablando?
JB

La tabla% c se declara y define en la primera línea; Sus personajes están perfectamente contabilizados.
JB

@JB oye, presioné accidentalmente el voto sobre tu respuesta y está bloqueado, ¿puedes editar esto para que pueda revertir el voto hacia abajo?
ciclohexanol.

67

Python (sin evaluación), 317 bytes

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

99
Ese es un hermoso ruido, señor
globby

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

50

Código de máquina de 16 bits 8086: 168 bytes

Aquí está la versión codificada en base64 , convierta y guarde como 'bf.com' y ejecute desde el símbolo del sistema de Windows: 'bf progname'

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

EDITAR

Aquí hay un ensamblador (estilo A86) para crear el ejecutable (¡tuve que aplicar ingeniería inversa a esto ya que había perdido la fuente original!)

    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

He agregado una versión del código fuente del programa. Acabo de notar que los caracteres que no son bf hacen que el programa salga en lugar de ser ignorado. Es fácil arreglar eso y lo dejaré como un ejercicio para que la gente lo haga ellos mismos.
Skizz

Recuerdo que obtuve la versión ELF de Linux 166 bytes, hace 10 años, aquí muppetlabs.com/~breadbox/software/tiny
Emmanuel

39

brainfuck , 843 691 bytes

Editar: decidí volver a visitar esto y encontré una sorprendente cantidad de formas de jugar al golf en bytes

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

Esto toma la entrada en la forma code!inputdonde el !inputes opcional. También simula celdas negativas sin usar celdas negativas y puede almacenar hasta (30000-(length of code+6))/2celdas.

Pruébalo en línea!


Solo para asegurarme de que lo hice bien, si ejecuté este programa con este programa, podría anidarlo en 5 niveles de profundidad y aún manejar entradas de código de longitud 262.
Draco18s

@ Draco18s Sospecho que se quedarían sin las 30000 celdas antes, ya que el tamaño de cada intérprete anidado aumenta exponencialmente. Creo que obtendrías 2, quizás 3 niveles de profundidad
Jo King

Incluso 3 de profundidad sería hilarantemente tonto.
Draco18s

27

Ruby 1.8.7, 188 185 149 147 caracteres

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

Versión algo legible:

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

Como puede ver, robé descaradamente su idea de traducir al idioma del host y luego usar eval para ejecutarlo.


Puede afeitarse un byte byte comparar a cero >0en lugar de probar la igualdad: !=0. Las especificaciones dicen sin firmar, y el desbordamiento no está definido.
cobarde anónimo

3e4también funcionará en lugar de30000
cobarde anónimo

@ Charlie: Gracias. Aunque para ser justos, no decía "sin firmar" cuando escribí el código. Sin embargo, sinceramente no sabía que podías escribir 3e4. Ese es un muy buen punto y es bueno saberlo.
sepp2k

File.read($*.pop).bytes-> $<.bytesdebería funcionar también
Arnaud Le Blanc

1
Ruby 1.8.7 tiene una sintaxis aún más corta para construir un hash literal: {?a,"foo"}que es equivalente a {?a=>"foo"}. Y probando aquí muestra que en realidad se puede sustituir File.read($*.pop).bytescon $<y sin ningún problema. Además, alinear todo a algo así eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";"acorta la solución con otros pocos caracteres.
Ventero

26

Cálculo Lambda Binario 112

El programa que se muestra en el volcado hexadecimal a continuación

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

espera que su entrada consista en un programa Brainfuck (mirando solo los bits 0,1,4 para distinguir entre, -. + <>] [) seguido de a], seguido de la entrada para el programa Brainfuck.

Guarde el volcado hexadecimal anterior con xxd -r> bf.Blc

Tome un intérprete blc de 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

Hola Mundo!


1
¿Por qué existe esto? Aparentemente, incluso existe en el ámbito de la investigación . Oo
Isiah Meadows

¿Entonces esto no funcionaría con los programas comentados de brainfuck?
kamoroso94

No, no sin quitar primero los comentarios.
John Tromp

18

0.8.2 retina , 386 391 386 bytes

El código contiene 0x00caracteres NUL ( ) no imprimibles . Tampoco está súper golfizado todavía, porque ya es muy lento, y si lo juego más, no sé cuánto tiempo tardaría en terminar. Parece que se agotó el tiempo de espera en la muestra de búsqueda principal.

Puede haber errores en el intérprete en línea o en mi programa (¿las nuevas líneas principales no se muestran en la salida?).

Toma entrada como <code>│<input>. No, eso no es una tubería ( |). Es el personaje de Unicode U+2502. El código también usa los caracteres Unicode ÿ▶◀├║. Los caracteres Unicode se utilizan para admitir la entrada de todos los caracteres ASCII. Por lo tanto, estos caracteres deben estar separados del código por un carácter no ASCII.

Pruébalo en línea

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

Tenga en cuenta que hay una nueva línea final allí.

Breve explicacion:

Los ceros 0x00se usan para la cinta, que es infinita. El primer reemplazo configura el intérprete en el formulario ▶<code>│<input>├<output>║▶<tape>, donde el primero es el puntero para el código, y el segundo es el puntero para la cinta.

ÿes 0xFF(255), que se utiliza para la transliteración (utilizada para implementar +y -) para envolver las celdas de nuevo a cero.

solo se usa para facilitar la lectura (en caso de que el programa se detenga en el medio o desee ver el programa a mitad de ejecución). De lo contrario, no podría saber en qué dirección se movía el puntero.

Código comentado:

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

Haga clic aquí para ver el código con ceros en lugar de bytes nulos. Cualquier ocurrencia de $0no debe ser reemplazado por nulos.

Editar : ahora admite entradas vacías y suprime la nueva línea final.

Salida infinita ahora es compatible. (403 bytes)


Desearía haber colocado el <code>y el <tape>uno al lado del otro (aunque serían más caracteres) para que la transición a un intérprete SMBF fuera más fácil, si alguna vez decidiera hacer eso.
mbomb007

14

TI-BASIC, 264 bytes

Debido a limitaciones en TI-BASIC, esto en realidad no califica para este desafío ya que infringe la regla 2; la RAM de la calculadora es muy limitada, y hacer algo como 30000->dim(L1(yo uso L1 para la pila / matriz) lo obligará a lanzar un ERR:MEMORY. Como tal, la pila / matriz comienza en un tamaño de 1 y crece si el puntero apunta a un elemento más allá del final. También infringe la regla 3, porque ya infringe la regla 2, por lo que es mejor no molestarme con un límite de tamaño de celda.

Probablemente todavía podría jugar golf, por cierto ... He realizado una o dos ediciones con ese fin desde la primera presentación, pero si la versión siguiente no funciona, vuelva a la edición del 6 de mayo de 2015 y utilícela. código en su lugar. Además, como realmente no hay ASCII en TI-BASIC, esto toma números de cualquier tamaño (y cualquier cosa que devuelva un número, como una variable o expresión) como entrada, y genera números a su vez.

Use SourceCoder para construirlo en un archivo .8xp y luego envíelo a su calculadora con TI-Connect o TILP o algo así, y ejecútelo incluyendo su programa brainfuck en comillas dobles seguido de dos puntos y lo que haya llamado el programa TI-BASIC. Por ejemplo, si usted lo nombró brainf, que había corrido un programa como este: "brainfuck goes here":prgmBRAINF. Si usted tiene una concha en su calc que intercepta otros comandos cuando se detecta la prgmseñal, sin embargo, hacer esto: "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

Si no tiene una manera de conectar su calculadora a su computadora y desea escribir esto en lugar de calc (no puedo imaginar por qué querría hacerlo, pero estoy divagando) tenga en cuenta que ->es el STO>botón que está arriba de ON clave, ~es el símbolo negativo al lado de ENTER, y para reemplazar todas las instancias de L<number>con el token de lista correspondiente encontrado en2ND -> <number on keypad>

Gracias a thomas-kwa (al menos, creo que ese es su nombre de usuario de Stack) por ayudarme a optimizar esto, especialmente con las instrucciones [y ].


1
¿Necesitas los padres alrededor Ans+S?
Zacharý

@ Zacharý Buena captura, no. Debo haber estado inseguro sobre cómo funciona PEMDAS o algo así ... Sin embargo, me abstendré de editar, porque ha pasado tanto tiempo que definitivamente no vale la pena subir esta publicación al frente y porque un byte de dos bytes la reducción no va a dar a la respuesta ningún tipo de ventaja sobre los demás jajaja.
MI Wright

1
Recuerdo como hace 2-3 años cuando utilicé este programa para interpretar Brainf *** en mi calculadora. Y, es una pregunta de interpretación mental, creo que debería estar en la cima para ser honesto.
Zacharý

1
En realidad, creo que toda la línea podría ser S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. ( a-a=0) Y oye, no te preocupes por olvidar UNA cosa de orden de operación aquí, he visto a una gran cantidad de personas olvidar el orden de operaciones para %(mod) en un desafío.
Zacharý

1
Oh dang, si. De acuerdo, eso da al menos 10 bytes de descuento, ya que el if también se puede hacer de una sola línea, además de algunas otras cosas ... también podría editar, entonces. Me has hecho sacar mi calculadora por primera vez en un año para comprobar esto, jaja
MI Wright

13

Python 275 248 255

Decidí probarlo.

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
Genial, estás generando código fuente de python usando brainfuck.

1
Puede quitar 1 carácter, "importar sys como s" y reemplazar "sys" por "s" en el resto
USTED

Tenga en cuenta que esto es en realidad 247 caracteres. (¿Ves el espacio desagradable después exec t?). Si usa la punta de S.Mark y también hace todo el forciclo en una línea, puede reducir esto a 243 caracteres.
Oleh Prypin

Esto falla en cualquier entrada que contenga []un programa bf válido aunque trivial. He sugerido una edición que corrige esto, pero aumenta el recuento de caracteres. Para reducir aún más el recuento de caracteres, puede from sys import *y usar en 'i+=1,...'.split(',')lugar de ['i+=1',...].
stand

77
Lo haría +1, pero se han sugerido muchas mejoras y no se han implementado.
mbomb007

12

Haskell, 457 413 caracteres

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

Este código "compila" el programa BF en una IOacción de la forma en que State -> IO Stateel estado es una cremallera en una cadena infinita.

Triste que tuve que gastar 29 caracteres para desactivar el almacenamiento en búfer. Sin eso, funciona, pero no ve las indicaciones antes de tener que escribir input. El compilador en sí ( b, fy k) se encuentra a sólo 99 caracteres, el tiempo de ejecución ( #y %) es 216. El conductor w / estado inicial otro 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 

actualización 15-02-2011: se incorporaron las sugerencias de JB, se modificó un poco el nombre y se endureciómain


1
Debería poder obtener el búfer de just IOy los argumentos de just System(-19). El problema del almacenamiento en búfer también me molesta, ya que la especificación realmente no lo menciona y la respuesta más votada ni siquiera hace E / S. Si debe conservarlo, probablemente sea más corto hFlushdespués de cada escritura que cambiar el modo de almacenamiento en búfer global (-34 + 15).
JB

11

Transportador, 953

Este podría ser el código más hermoso que jamás haya 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
¿Podría agregar una explicación y un enlace a una implementación? Quiero entender la belleza ;)
DLosc

1
Bueno, actualmente lo estoy desarrollando, hay un compilador y una muy mala explicación en github.com/loovjo/Conveyor . La fuente es bastante legible si quieres entenderla.
Loovjo

9

C 284 362 (de un archivo)

#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:

Primes hasta: 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
Pulse cualquier tecla para continuar . . .

Compilado y ejecutado con éxito VS2008

La solución original no pudo reconocer los bucles que inicialmente se establecieron en cero. Todavía hay espacio para el golf. Pero finalmente resuelve el programa Prime Number.

Sin golf:

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

Pruebas:

Hola Mundo

Rot13


¿Está comprobando el mismo puntero ( l) cada vez que realiza un bucle? Creo que se supone que debes verificar la ubicación actual de la cabeza ( p).
Alexandru

Paso el puntero al búfer y el puntero a la secuencia. Comprueba al final del ciclo para ver si el puntero len el búfer ha llegado a cero y se rompe; de ​​lo contrario, restablece la secuencia al ciclo original [. Esto es necesario para los [bucles anidados .
snmcdonald

1
Sí. Ya me lo imaginaba. No debe verificar el valor en el puntero al entrar primero en el bucle, sino el valor en el puntero actual. Verifique la prueba en la pregunta. Tu programa se cuelga.
Alexandru

1
Puedes reemplazar break;elsepor return;.
Alexandru

3
Creo que puedes reemplazarlo (c==62)?a:bcon (c-62)?b:a.
Alexandru

9

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

Le di una oportunidad sin usar eval, pero finalmente tuve que usarlo

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

Todos los comandos están funcionando. Esto abusa mucho de las variables variables y arroja advertencias. Sin embargo, si uno cambia su php.ini a advertencias de silenciamiento (o canaliza stderr a / dev / null), esto funciona muy bien.

Verificación (es el ejemplo "Hello World!" De Wikipedia ): http://codepad.viper-7.com/O9lYjl

Sin golf, 367 365 335 296 267 caracteres:

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

Esto debe ejecutarse a través de la línea de 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

Conversión bastante sencilla de las instrucciones y luego Invoke-Expression.

Historia:

  • 2011-02-13 22:24 (220) Primer intento.
  • 2011-02-13 22:25 (218) 3e4es más corto que 30000.
  • 2011-02-13 22:28 (216) Saltos de línea innecesarios. La coincidencia en enteros en lugar de caracteres es más corta.
  • 2011-02-13 22:34 (207) Se utilizaron índices en una tabla hash en lugar de switch.
  • 2011-02-13 22:40 (205) Mejor conversión a cadena elimina dos paréntesis.
  • 2011-02-13 22:42 (204) No es necesario un espacio después del argumento para Write-Host.

8

C, 333 caracteres

Este es mi primer intérprete BF y el primer golf que tuve que depurar.

Esto ejecuta el generador de números primos en Mac OS X / GCC, pero #include<string.h>puede ser necesario un adicional a un costo de 19 caracteres más si la definición implícita de strchrno funciona en otra plataforma. Además, se supone O_RDONLY == 0. Aparte de eso, dejar de intlado la declaración de Mguardar 3 caracteres, pero eso no parece ser compatible con C99. Lo mismo con la tercera *en b().

Esto depende de los detalles de la codificación ASCII. Los operadores Brainfuck son todos pares complementarios separados por una distancia de 2 en el espacio de código ASCII. Cada función en este programa implementa un par de operadores.

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

Creo que puedes reducirlo más usando la notación 'e' para todos los números grandes.
luser droog

@luser: Al principio también me sorprendió, pero el lenguaje y el compilador no lo permitirán. Me las arreglé para reducir otros 4 caracteres con ajustes, y el uso de una #definetabla en lugar de la función también sería probablemente más terser. Simplemente me gusta el número 333 y la tabla: v).
Potatoswatter

Correcto. Realmente debería haberlo sabido. La notación E está en producción para una constante de punto flotante, mientras que una declaración requiere un número entero. Por cierto, esto puede ser una trampa, pero echa un vistazo a nieko.net/projects/brainfuck para la versión de Urban Müller. La mayor ganancia parece ser el uso intensivo de ||.
luser droog

8

CJam, 75 bytes

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

Pruébelo en línea: inversor de cadenas , Hello World .

Explicación

Toma código en la primera línea de STDIN e ingresa en todas las líneas debajo de él.

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.

¿Qué hay de esa lista mágica?

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

La lista resultante es la siguiente:

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)

Generamos los fragmentos para +y >desde aquellos para -y <, simplemente cambiando los parentes izquierdos ("decremento" de CJam) en parens derechos ("incremento" de CJam).


Respuesta más corta y mayor ganador
Jack Giffin

7

F #: 489 caracteres

El siguiente programa no salta a las instrucciones '[' / ']', sino que escanea el código fuente para el siguiente token coincidente. Por supuesto, esto lo hace un poco lento, pero aún puede encontrar los números primos por debajo de 100. Los tipos enteros F # no se desbordan sino que se ajustan.

Aquí está la versión corta:

[<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 problema desagradable fue que el programa primes.bf se ahoga en las nuevas líneas de Windows. Para ejecutarlo, tuve que guardar el número de entrada en un documento de texto con formato UNIX y alimentarlo al programa con una tubería:

interpret.exe prime.bf < number.txt

Editar: ingresar Alt + 010 seguido de Enter también funciona en Windows cmd.exe

Aquí está la versión más larga:

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

Resolví el problema de Enter no presionándolo, pero Ctrl + J :-)
Joey

Ctrl + J no funcionó para mí, pero al ingresar Alt + 010 seguido de Enter sí.
cfern

7

Delphi, 397 382 378 371 366 364 328 caracteres

¡Comete este 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.

Aquí el mismo código, sangrado y comentado:

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.

Este me llevó unas horas, ya que no es el tipo de código que normalmente escribo, ¡pero disfrútalo!

Nota: La prueba principal funciona, pero no se detiene en 100, porque dice # 13 (CR) antes de # 10 (LF) ... ¿otras presentaciones también sufren este problema cuando se ejecutan en sistemas operativos CRLF?


¡Guauu! ¡Nunca hubiera esperado vencer a C en brevedad con Delphi! No hasta que aplique mis ideas a la conjetura de CI ;-)
PatrickvL

7

C, 260 + 23 = 283 bytes

Creé un programa en C que se puede encontrar aquí .

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

Tiene que compilarse a través de gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.cy se puede invocar de la siguiente manera: pmmbf ",[.-]" 30000mediante el cual el primer argumento (citado) contiene el programa bf para ejecutar, el segundo determina qué tan grande debe ser la cinta.


1
Creo que necesita agregar 23 caracteres a su recuento para la -D"q(a,b)"="*c-a||(b);"opción, ya que eso parece (al menos para mi comprensión limitada) ayudarlo a reducir su código.
Gareth

La opción está incluida en el texto publicado. La razón es evitar la palabra larga definey la nueva línea, pero no creo que sea realmente kosher. De todos modos con las citas, comentarios, y gcc -Dno veo la ventaja en absoluto.
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);}

Ejecutar como ./a.out primes.bf

Versión sin golf:

#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

Pitón 2, 223

Admito que reciclé un programa antiguo mío (pero tuve que cambiarlo un poco, porque la versión anterior no tenía entrada, pero la comprobación de errores ...).

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

Ejecuta bien la calculadora de primos.

Ahora veo que Alexandru tiene una respuesta que tiene algunas similitudes. Publicaré mi respuesta de todos modos, porque creo que hay algunas ideas nuevas.


5

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

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

Pruébalo en línea!

Este es un JIT que compila código BF en lenguaje máquina x86_64 en tiempo de ejecución. Este realiza una traducción recta de manera que ocurren comúnmente secuencias tales como >>>, <<<, +++y ---no se unió en instrucciones más rápidos.

Versión menos golfizada:

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

Lee de un archivo. Pasa la prueba PRIME.BF.

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


Reformateado:

#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. Su búfer es demasiado pequeño. El tamaño del programa es demasiado pequeño también.
Alexandru

Hice un error tipográfico, arreglado. ¿Qué quieres decir con el tamaño del programa? Si te refieres al tamaño máximo de archivo, no especificaste un mínimo que debería manejar.
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]"))()

Versión algo legible:

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

Funciona perfectamente

Lua, 478, sin cuerda de carga

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

Versión legible:

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 bytes

Bueno, eso tomó un tiempo. Jugué un auto-intérprete Brainfuck por ... no yo.

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

4

Retiro , 594 bytes

En resumen: Recall no tiene operadores aritméticos en un sentido clásico, solo tiene operaciones bit a bit. No puede simplemente "agregar uno", etc. La recuperación también está estrictamente basada en la pila.

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

Ejemplo 1: imprimir algo

Entrada:

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

Salida:

PPCG rocks!

Ejemplo 2: números cuadrados de salida hasta 100

Entrada:

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

Salida:

0
1
4
9
16
25
36
49
64
81
100

Este ejemplo puede tardar unos minutos en ejecutarse y puede provocar el mensaje "esta pestaña está congelada". Ignora eso y espera.


44
El dominio de su sitio web ha caducado. Además, esta respuesta no es competitiva, porque el lenguaje es más nuevo que el desafío.
mbomb007

3

OCaml (lex), 497 caracteres

OCamllex es parte de la distribución estándar de 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}

Guardar como b.mll y ejecutar con

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

No me gusta analizar a mano, así que utilicé el generador lexer provisto. A partir de los tokens leídos, componimos una función para todo el programa brainf * ck.


3

C # (2861 caracteres, ~ 84 líneas)

Esta no es la solución más bonita para el problema, y ​​probablemente no sea todo ese 'Golf-ish', ya que no estaba tan preocupado por la longitud como probablemente debería haber estado. (No eliminé los comentarios ni el espacio en blanco adicional). Solo quería probar algo en un nuevo idioma, para ver si podía. Si lo volviera a hacer, abandonaría el uso de la pila para volver de ']' y solo miraría hacia atrás. Ejecutar sin argumentos de línea de comando, ejecuta el programa hello world que se proporciona en la descripción del problema. Acepta un argumento de línea de comando, el nombre de archivo del programa a ejecutar.

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

        }
    }

}

Editar: se eliminaron las referencias no utilizadas.


1
@ mbomb007 - Actualizado. Completamente olvidado, incluso hice este. (Ni siquiera me
di

No solo las personas los siguen leyendo, sino que también responden y los juegan golf.
mbomb007

3

C (gcc) , 273 268 bytes

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

Pruébalo en línea!

-5 gracias a ceilingcat

Toma información de stdin.

Esto depende un poco del medio ambiente, pero es bastante consistente. Esta es efectivamente la solución de evaluación para c. Escribe un programa C apropiado en el archivo wc, lo compila y lo ejecuta como el ejecutable deseado. Por lo tanto, como efecto adicional, esto realmente compila el código bf y lo deja a.outcomo un binario. Tenga en cuenta que, según el sistema, es posible que deba modificar la última cadena. En particular, la mayoría de los compiladores de Windows C llaman al ejecutable predeterminado "a.exe". Afortunadamente, por lo que puedo decir, todos tienen la misma longitud, por lo que el bytecount es el mismo. (aunque si no tiene un cc definido, es posible que deba agregar una letra como gcc al comando de compilación, agregando 1 byte).

Soy consciente de que este hilo es un poco viejo, pero todavía no vi este estilo de solución C, así que pensé en agregarlo.



2

[EDITAR]

C ++ 11, 355, lee del archivo:

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

Prueba

http://ideone.com/b7vO4

[VERSIÓN ANTIGUA]

C ++ 11, 391, para ver en ejecución: 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]();
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.