Interpretar o cérebro ***


113

Escreva o programa mais curto no seu idioma favorito para interpretar um programa de foda cerebral . O programa é lido de um arquivo. Entrada e saída são entrada e saída padrão.

  1. Tamanho da célula: 8 bits sem sinal. O estouro é indefinido.
  2. Tamanho da matriz: 30000 bytes (não circulado)
  3. Comandos incorretos não fazem parte da entrada
  4. Os comentários começam com # e se estendem até o fim da linha comentários são tudo não em+-.,[]<>
  5. nenhum símbolo EOF

Um teste muito bom pode ser encontrado aqui . Ele lê um número e depois imprime os números primos até esse número. Para evitar a podridão do link, aqui está uma cópia do 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========

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

Exemplo de execução:

$ 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
Você deve esclarecer sobre 1) tamanho da memória 2) é a memória circulou 4) talvez quaisquer outros detalhes
Nakilon

3
Gostaria de saber se deve haver duas categorias: os programas que usam eval (ou shell out para compilar) - e aqueles que não.
MtnViewMark 15/02

34
Eu adoraria ver alguém responder isso no cérebro.
Hannesh 14/03/11

3
O que significa "nenhum símbolo EOF"? Que o valor da célula permanece inalterado ao experimentar o ,EOF? Ou que cabe a nós escolher um valor ao experimentar o ,EOF? Ou o comportamento indefinido do EOF é totalmente?
Martin Ender

3
Da mesma forma, o que deve acontecer quando alguém tenta deixar as células de 30k de cada lado? A cabeça da fita deve permanecer no lugar ou esse comportamento é indefinido?
Martin Ender

Respostas:


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

Isso executa hello.bf e primes.bf na perfeição:

$ 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

Inicialização: O opcode para a tabela de conversão Perl é armazenado %c. A forma legível fica assim:

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

Etapa 1: Slurp a entrada do programa $_e a transforme em código Perl usando a tabela de conversão. Os comentários são automaticamente removidos (substituídos por undef) nesta etapa.

Etapa 2: descompacte todas as $b[$p]ocorrências

Etapa 3: inicie o programa usando eval.


Basta usar a qwsintaxe do Perl para definir %cdiretamente - bom para 7 caracteres a menos (você terá que dizer print+chr$b[$p]e ord(getc), no entanto)
mob

Conto 18 salvos ... obrigado! (atualizando em um minuto)
JB

1
@olivecoder De que diabos você está falando?
JB

A tabela% c é declarada e definida na primeira linha; seus personagens são perfeitamente explicados.
JB

@JB ei, eu acidentalmente pressionei voto na sua resposta e ela está bloqueada, você pode editar isso para que eu possa reverter o voto?
ciclohexanol.

67

Python (sem avaliação), 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 of(u,c,k)
Joel Cornett

9
Essa é uma bela peça de ruído, senhor
globby

-1 byte se você substituir while b*c[c[0]]and j<1porwhile b*c[c[0]]*(j<1)
Daniil Tutubalin

50

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

Aqui está a versão codificada em base64 , converta e salve como 'bf.com' e execute no prompt de comando do Windows: 'bf progname'

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

EDITAR

Aqui está um montador (estilo A86) para criar o executável (eu tive que fazer engenharia reversa disso, pois havia extraviado a fonte 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

Eu adicionei uma versão do código fonte do programa. Acabei de notar que caracteres não-bf fazem com que o programa saia em vez de ser ignorado. Fácil de consertar isso e vou deixar isso como um exercício para as pessoas fazerem isso sozinhas.
Skizz

Eu lembro que obtive a versão Linux ELF 166 bytes, 10 anos atrás, aqui muppetlabs.com/~breadbox/software/tiny #
Emmanuel

39

brainfuck , 843 691 bytes

Edit: decidiu revisitar isso e encontrou um número surpreendente de maneiras de jogar fora os bytes

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

Isso recebe a entrada no formato em code!inputque !inputé opcional. Também simula células negativas sem usar as próprias células negativas e pode armazenar até (30000-(length of code+6))/2células.

Experimente online!


Só para garantir que eu entendi direito, se eu executasse este programa com este programa, eu poderia aninhar 5 níveis de profundidade e ainda manipular entradas de código de comprimento 262.
Draco18s

@ Draco18s Eu suspeito que você esgotaria as 30000 células antes disso, pois o tamanho de cada intérprete aninhado aumenta exponencialmente. Eu acho que você terá 2, talvez 3 níveis de profundidade
Jo King

Mesmo 3 profundos seria hilariamente bobo.
Draco18s

27

Ruby 1.8.7, 188 185 149 147 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]}*";"

Versão um pouco legível:

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 você vê, roubei descaradamente a sua ideia de traduzir para o idioma host e usar eval para executá-lo.


Você pode raspar um byte byte comparação a zero >0em vez de testar a igualdade: !=0. As especificações dizem não assinado e o excesso não é definido.
covarde anônimo

3e4também irá trabalhar em oposição a30000
Covarde Anônimo

@ Charlie: Obrigado. Embora seja justo, não disse "sem assinatura" quando escrevi o código. Honestamente, eu não sabia que você poderia escrever 3e4. Esse é um ponto muito bom e bom saber.
sepp2k

File.read($*.pop).bytes-> $<.bytesdeve funcionar também
Arnaud Le Blanc

1
O Ruby 1.8.7 possui uma sintaxe ainda mais curta para criar um hash literal:, {?a,"foo"}que é equivalente a {?a=>"foo"}. E os testes aqui mostram que você pode substituí File.read($*.pop).bytes-lo $<sem problemas. Também incluir tudo em algo como eval"a[0]..."+$<.bytes.map{?.,"putc a[i]",...}*";"reduz a solução em mais alguns caracteres.
Ventero 14/02

26

Cálculo binário Lambda 112

O programa mostrado no dump hexadecimal abaixo

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 sua entrada consista em um programa Brainfuck (olhando apenas os bits 0,1,4 para distinguir entre -. + <>] [) seguido de a], seguido pela entrada do programa Brainfuck.

Salve o dump hexadecimal acima com xxd -r> bf.Blc

Pegue um intérprete do blc em 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

Olá Mundo!


1
Por que isso existe? Aparentemente, existe até no campo da pesquisa . Oo
Isiah Meadows

Portanto, isso não funcionaria com programas comentados de cérebro?
kamoroso94

Não, não sem retirar os comentários primeiro.
John Tromp

18

Retina 0.8.2 , 386 391 386 bytes

O código contém 0x00caracteres NUL ( ) não imprimíveis . Também não é super golfado ainda, porque já é muito lento, e se eu jogar mais, não sei quanto tempo levaria para terminar. Parece esgotar o tempo limite na amostra de localização privilegiada.

Pode haver erros no intérprete online ou no meu programa (novas linhas principais não aparecem na saída?).

Toma entrada como <code>│<input>. Não, isso não é um pipe ( |). É o caractere Unicode U+2502. O código também usa os caracteres Unicode ÿ▶◀├║. Caracteres Unicode são usados ​​para suportar a entrada de todos os caracteres ASCII. Portanto, esses caracteres precisam ser separados do código por um caractere não ASCII.

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

Observe que há uma nova linha final lá.

Breve explicação:

Zeros 0x00são usados ​​para a fita, que é infinita. A primeira substituição configura o intérprete no formulário ▶<code>│<input>├<output>║▶<tape>, onde o primeiro é o ponteiro para o código e o segundo é o ponteiro para a fita.

ÿé 0xFF(255), que é usado para transliteração (usada para implementar +e -) para quebrar as células de volta a zero.

é usado apenas para facilitar a leitura (caso o programa seja interrompido no meio ou você queira ver o programa no meio da execução). Caso contrário, você não poderia dizer para que lado o ponteiro estava se movendo.

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

Clique aqui para o código com zeros no lugar de bytes nulos. Quaisquer ocorrências de $0não devem ser substituídas por nulos.

Editar : agora suporta entrada vazia e suprime a nova linha à direita.

Saída infinita agora é suportada. (403 bytes)


Eu meio que gostaria de ter colocado o <code>e o <tape>próximo um do outro (embora houvesse mais caracteres) para que a transição para um intérprete SMBF fosse mais fácil, se eu decidisse fazer isso.
mbomb007

14

TI-BASIC, 264 bytes

Devido às limitações no TI-BASIC, isso não se qualifica para esse desafio, pois quebra a regra 2; a RAM das calculadoras é muito limitada, e fazer algo do tipo 30000->dim(L1(eu uso L1 para a pilha / matriz) forçará o lançamento de um ERR:MEMORY. Como tal, a pilha / matriz começa no tamanho de 1 e cresce se o ponteiro estiver apontando para um elemento após o final dele. Ele também viola a regra 3, porque já está violando a regra 2, então é melhor não me preocupar com um limite de tamanho de célula.

Provavelmente ainda pode ser jogado, a propósito ... Eu fiz uma ou duas edições para esse fim desde o primeiro envio, mas se a versão abaixo não funcionar, volte para a edição de 6 de maio de 15 e use-a código em vez disso. Além disso, como realmente não há ASCII no TI-BASIC, isso leva números de qualquer tamanho (e qualquer coisa que retorne um número, como uma variável ou expressão) como entrada e gera números por vez.

Use o SourceCoder para compilá-lo em um arquivo .8xp e depois envie-o para a sua calculadora com TI-Connect ou TILP ou algo assim, e execute-o incluindo seu programa de foda cerebral entre aspas duplas seguido por dois-pontos e qualquer que seja o nome do programa TI-BASIC. Por exemplo, se você é chamado BRAINF, você executar um programa como este: "brainfuck goes here":prgmBRAINF. Se você tem um escudo em seu calc que intercepta outros comandos quando detecta o prgmsinal, porém, fazer isso: "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 você não tem como conectar sua calculadora ao computador e deseja digitar isso no cálculo (não consigo imaginar por que você gostaria, mas discordo), observe que ->é o STO>botão acima do botão ON , ~é o símbolo negativo ao lado de ENTER e substitui todas as instâncias L<number>pelo token de lista correspondente encontrado em2ND -> <number on keypad>

Agradeço a thomas-kwa (pelo menos, acho que esse é o nome de usuário do Stack) por me ajudar a otimizar isso, especialmente com as instruções [e ].


1
Você precisa das parênteses Ans+S?
Zacharý 7/07

@ Zacharý Boa captura, não. Eu devo estar inseguro sobre como o PEMDAS funciona ou algo assim ... Abster-me-ei de editar, no entanto, porque faz tanto tempo que definitivamente não vale a pena dar um pulo nesta postagem com antecedência e porque um byte de dois bytes redução não vai dar à resposta nenhum tipo de vantagem sobre os outros, lol.
MI Wright

1
Lembro-me de 2-3 anos atrás, quando usei este programa para interpretar Brainf *** na minha calculadora. E, é uma questão de interpretar o cérebro, acho que deveria estar no topo para ser honesto.
Zacharý

1
Na verdade, acho que toda essa linha poderia ser S-sum(not(cumSum(L4(Ans)=seq(L4(X),X,Ans+1,dim(L4->S. ( a-a=0) E ei, não se preocupe em esquecer UMA coisa de ordem de operação aqui, já vi várias pessoas esquecerem a ordem de operações para %(mod) em um desafio.
Zacharý

1
Oh caramba, sim. Ok, isso fornece pelo menos 10 bytes de desconto, já que o if também pode ser transformado em uma linha, além de algumas outras coisas ... também pode editar. Você me fez sacar minha calculadora pela primeira vez em como um ano para verificar essas coisas, haha
MI Wright

13

Pitão 275 248 255

Eu decidi tentar.

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
Legal, você está gerando código-fonte python usando brainfuck.

1
Pode retirar um carvão animal, "import sys como s" e substituir "sys" a "S" no descanso
VOCÊ

Observe que na verdade são 247 caracteres. (Veja o espaço desagradável depois exec t?). Se você usar a dica de S.Mark e também transformar todo o forciclo em uma linha, poderá reduzi-lo para 243 caracteres.
Oleh Prypin

Isso falha em qualquer entrada que contenha []um programa bf válido, embora trivial. Sugeri uma edição que corrige isso, mas aumenta a contagem de caracteres. Para reduzir ainda mais a contagem de caracteres, você pode from sys import *usar e 'i+=1,...'.split(',')não usar ['i+=1',...].
Boothby

7
Eu teria +1, mas muitas melhorias foram sugeridas e não implementadas.
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

Esse código "compila" o programa BF em uma IOação da forma em que State -> IO Stateo estado é um zíper em uma sequência infinita.

Infelizmente, eu tive que gastar 29 caracteres para desativar o buffer. Sem eles, ele funciona, mas você não vê os prompts antes de digitar input. O compilador si ( b, f, e k) é apenas de 99 caracteres, o tempo de execução ( #e %) é 216. O motorista w / estado inicial outra 32.

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

>./BF HELLO.BF 
Hello World!

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

update 2011-02-15: Incorporou as sugestões de JB, renomeou um pouco e reforçoumain


1
Você deve conseguir obter o buffer de apenas IOe os argumentos de apenas System(-19). O problema de buffer também me incomoda, pois as especificações realmente não o mencionam e a resposta mais votada nem sequer faz E / S. Se você precisar mantê-lo, provavelmente será mais curto hFlushdepois de cada gravação do que alterar o modo de buffer global (-34 + 15).
JB

11

Transportadora, 953

Este pode ser o código mais bonito que você verá:

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
Você poderia adicionar uma explicação e um link para uma implementação? Eu quero entender a beleza. ;)
DLosc

1
Bem, no momento estou desenvolvendo, existe um compilador e uma explicação muito ruim em github.com/loovjo/Conveyor . A fonte é bastante legível se você quiser entendê-la.
Loovjo

9

C 284 362 (De um arquivo)

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

Primos até: 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
Pressione qualquer tecla para continuar . . .

Compilado e executado com sucesso VS2008

A solução original falhou ao reconhecer os loops que foram inicialmente definidos como zero. Ainda há espaço para jogar golfe. Mas finalmente resolve o programa 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);
}

Testes:

Olá Mundo

Rot13


Você está verificando o mesmo ponteiro ( l) toda vez que faz um loop? Eu acho que você deve verificar a localização atual da cabeça ( p).
Alexandru

Eu passo o ponteiro para o buffer e o ponteiro para o fluxo. Ele verifica no final do loop para ver se o ponteiro lno buffer atingiu zero e interrompe, caso contrário, redefine o fluxo de volta ao loop original [. Isso é necessário para [loops aninhados .
snmcdonald

1
Sim. Eu pensei assim. Você não deve verificar o valor no ponteiro na primeira entrada no loop, mas o valor no ponteiro atual. Verifique o teste na pergunta. Seu programa trava.
Alexandru

1
Você pode substituir break;elsepor return;.
Alexandru

3
Eu acho que você pode substituir (c==62)?a:bpor (c-62)?b:a.
Alexandru

9

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

Eu tentei sem usar o eval, mas eventualmente tive que usá-lo

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

Todos os comandos estão funcionando. Isso abusa fortemente de variáveis ​​variáveis ​​e vomita avisos. No entanto, se alguém mudar seu php.ini para silenciar avisos (ou canalizar stderr para / dev / null), isso funcionará muito bem.

Verificação (é o exemplo "Hello World!" Da Wikipedia ): http://codepad.viper-7.com/O9lYjl

Ungolfed, 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);

Isso deve ser executado através da linha 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

Conversão bastante direta das instruções e, em seguida Invoke-Expression.

História:

  • 13-02-2011 22:24 (220) Primeira tentativa.
  • 2011-02-13 22:25 (218) 3e4é mais curto que 30000.
  • 2011-02-13 22:28 (216) Quebras de linha desnecessárias. A correspondência em números inteiros em vez de caracteres é mais curta.
  • 13-02-2011 22:34 (207) Utilizou índices em uma tabela de hash em vez de switch.
  • 13-02-2011 22:40 (205) Melhor conversão para string remove dois parênteses.
  • 2011-02-13 22:42 (204) Não há necessidade de espaço após a discussão Write-Host.

8

C, 333 caracteres

Este é o meu primeiro intérprete de BF e o primeiro golfe que eu tive que depurar.

Isso executa o gerador de números primos no Mac OS X / GCC, mas #include<string.h>pode ser necessário um adicional a um custo de 19 caracteres a mais, se a definição implícita de strchrnão funcionar em outra plataforma. Além disso, assume O_RDONLY == 0. Além disso, deixar de intfora a declaração de Msalvar três caracteres, mas isso não parece ser compatível com C99. Mesmo com o terceiro *em b().

Isso depende dos detalhes da codificação ASCII. Os operadores Brainfuck são todos pares complementares separados por uma distância de 2 no espaço de código ASCII. Cada função neste programa implementa um 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]();
}

Eu acho que você pode diminuir ainda mais usando a notação 'e' para todos os grandes números.
Luser droog

@user: Também fiquei surpreso inicialmente, mas o idioma e o compilador não permitem isso. #defineConsegui reduzir outros 4 caracteres com ajustes, e usar uma tabela em vez da função também provavelmente seria terser. Eu apenas gosto do número 333 e da tabela: v).
Potatoswatter 16/08/19

Oh, certo. Eu realmente deveria saber disso. A notação E está na produção de uma constante de ponto flutuante, enquanto uma declaração requer um número inteiro. BTW, isso pode ser trapaça, mas confira nieko.net/projects/brainfuck para a versão de Urban Müller. O maior ganho parece ser o uso pesado de ||.
Luser droog

8

CJam, 75 bytes

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

Experimente on-line: reversor de string , Olá Mundo .

Explicação

Pega código na primeira linha do STDIN e insere em todas as linhas abaixo dele.

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

A lista resultante é a seguinte:

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)

Geramos os trechos para +e >daqueles -e para <, simplesmente alterando os parênteses à esquerda ("decremento" de CJam) em parênteses à direita ("incremento") de CJam.


Shortest resposta e maior vencedor
Jack Giffin

7

F #: 489 caracteres

O programa a seguir não pula nas instruções '[' / ']', mas verifica o código-fonte para o próximo token correspondente. É claro que isso fica meio lento, mas ainda é possível encontrar os números primos abaixo de 100. Os tipos inteiros de F # não transbordam, mas envolvem.

Aqui está a versão curta:

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

Uma pegadinha desagradável foi que o programa primes.bf engasga com as novas linhas do Windows. Para executá-lo, tive que salvar o número de entrada em um documento de texto formatado em UNIX e alimentá-lo no programa com um pipe:

interpret.exe prime.bf < number.txt

Editar: inserir Alt + 010 seguido de Enter também funciona no Windows cmd.exe

Aqui está a versão mais longa:

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

Eu resolvi o problema Digite não pressionando, mas Ctrl + J :-)
Joey

Ctrl + J não funcionou para mim, mas inserir Alt + 010 seguido de Enter funcionaram.
cfern

7

Delphi, 397 382 378 371 366 364 328 caracteres

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

Aqui o mesmo código, recuado e 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 levou algumas horas, pois não é o tipo de código que eu normalmente escrevo, mas aproveite!

Nota: O teste principal funciona, mas não para em 100, porque lê # 13 (CR) antes de # 10 (LF) ... outros envios também sofrem esse problema ao executar em sistemas operacionais CRLF?


Uau! Eu nunca teria esperado superar C em discrepância com Delphi! Não até que você aplicar minhas idéias para adivinhar CI ;-)
PatrickvL

7

C, 260 + 23 = 283 bytes

Eu criei um programa C que pode ser encontrado aqui .

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

Precisa ser compilado via gcc -D"q(a,b)"="*c-a||(b);" -o pmmbf pmmbf.ce pode ser chamado da seguinte maneira: pmmbf ",[.-]" 30000pelo qual o primeiro argumento (citado) contém o programa bf a ser executado, o segundo determina o tamanho da fita.


1
Eu acho que você precisa adicionar 23 caracteres à sua contagem para a -D"q(a,b)"="*c-a||(b);"opção, pois isso parece (pelo menos para o meu entendimento) estar ajudando você a reduzir seu código.
Gareth

A opção está incluída no texto postado. A razão disso é evitar a palavra longa definee a nova linha, mas não acho que seja realmente kosher. De qualquer forma, com as citações, comente e gcc -Dnão vejo a vantagem.
Potatoswatter 6/08/11

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

Execute como ./a.out primes.bf

Versão 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

Admito que reciclei um programa antigo meu (mas tive que alterá-lo um pouco, porque a versão antiga não tinha entrada, mas verificação de erro ...).

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

Executa a calculadora de números primos bem.

Vejo agora que Alexandru tem uma resposta que tem algumas semelhanças. Vou postar minha resposta de qualquer maneira, porque acho que há algumas idéias novas nela.


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

Experimente online!

Este é um JIT que compila o código BF na linguagem de máquina x86_64 em tempo de execução. Isso realiza uma tradução recta de modo que ocorre comumente sequências, tais como >>>, <<<, +++e ---não são fundiram-se em instruções mais rápidos.

Versão menos golfe:

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

Lê de um arquivo. Passa no teste 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;}}


Reformatado:

#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. Seu buffer é muito pequeno. O tamanho do programa também é muito pequeno.
Alexandru

Eu fiz um erro de digitação, consertado. O que você quer dizer com tamanho do programa? Se você quer dizer o tamanho máximo do arquivo, não especificou o mínimo que ele deve tratar.
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]"))()

Versão um pouco legível:

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 perfeitamente

Lua, 478, sem 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

Versão legível:

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

Bem, isso levou um tempo. Joguei um auto-intérprete de Brainfuck por ... não eu.

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

4

Lembre-se , 594 bytes

Em resumo: a Recall não possui operadores aritméticos no sentido clássico, apenas possui operações bit a bit. Você não pode simplesmente "adicionar um" etc. A rechamada também é estritamente baseada em pilha.

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

Exemplo 1: Imprimir algo

Entrada:

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

Resultado:

PPCG rocks!

Exemplo 2: números quadrados de saída até 100

Entrada:

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

Resultado:

0
1
4
9
16
25
36
49
64
81
100

Este exemplo pode demorar alguns minutos para ser executado e pode causar uma mensagem "esta guia está congelada". Ignore isso e espere.


4
O domínio do seu site expirou. Além disso, essa resposta não é competitiva, porque o idioma é mais novo que o desafio.
mbomb007

3

OCaml (lex), 497 caracteres

OCamllex faz parte da distribuição padrão do 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}

Salve como b.mll e execute com

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

Como não gosto de analisar manualmente, usei o gerador de lexer fornecido. A partir das fichas lidas, compomos uma função para todo o programa brainf * ck.


3

C # (2861 caracteres, ~ 84 linhas)

Essa não é a solução mais bonita para o problema, e provavelmente não é tudo isso 'Golf-ish', já que eu não estava tão preocupado com o comprimento quanto provavelmente deveria estar. (Não removi os comentários ou espaço em branco extra.) Só queria tentar algo em um novo idioma, para ver se era possível. Se eu fizesse novamente, abandonaria o uso da pilha para retornar de ']' e apenas olharia para trás. Executar sem argumentos de linha de comando, ele executa o programa hello world fornecido na descrição do problema. Ele aceita um argumento de linha de comando, o nome do arquivo do programa a ser executado.

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: referências não utilizadas removidas.


1
@ mbomb007 - Atualizado. Esqueci completamente que eu até fiz esse. (Nem percebi que alguém sequer leu essas perguntas antigas)
theB

As pessoas não apenas as leem, mas também as respondem e jogam golfe.
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");};

Experimente online!

-5 graças a ceilingcat

Recebe entrada de stdin.

Isso depende um pouco do ambiente, mas é bastante consistente. Esta é efetivamente a solução de avaliação para c. Ele grava um programa C apropriado no arquivo wc, o compila e o executa como o executável desejado. Assim, como efeito bônus, na verdade, ele compila o código bf e o deixa a.outcomo um binário. Observe que, dependendo do sistema, pode ser necessário modificar a última string. Em particular, a maioria dos compiladores do Windows c chama o executável padrão "a.exe". Felizmente, tanto quanto posso dizer, todos têm o mesmo comprimento, portanto o número de bytes é o mesmo. (embora se você não tiver um cc definido, poderá ser necessário adicionar uma letra como gcc ao comando compile, adicionando 1 byte).

Estou ciente de que esse segmento é um pouco antigo, mas ainda não vi esse estilo de solução C, então pensei em adicioná-lo.



2

[EDITAR]

C ++ 11, 355, lê do arquivo:

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

Teste

http://ideone.com/b7vO4

[VERSÃO ANTIGA]

C ++ 11, 391, para ver em execução: 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]();
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.