Minify Brainfuck

22

Seu desafio é reduzir o código Brainfuck , de acordo com estas regras:

  • Remova qualquer coisa que não seja uma +-><[].,.
  • Para qualquer grupo de consecutivo +ou -caracteres, se a quantidade de +s e -s é o mesmo, removê-los.
  • Faça o mesmo que acima, mas com >e <.
  • Remova as seqüências dos +-><caracteres se eles não fizerem nada. Por exemplo, você deve remover +>-<->+<. (Esse pode ser o mais difícil e difícil de implementar.) Certifique-se de que não obtém nenhum falso positivo, como +>-<+>-<, que não deve ser removido.

Casos de teste:

Entrada

++++++[->++++++<]>.   prints a $
[-]<                  resets tape
>,[>,]<[.<]           reverses NUL terminated input string
++-->><<              does nothing

Saída

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

Entrada

Should disappear: ++>>+<+++<->-->-<<->-<
Should disappear: +++>-<--->+<
Should stay: +++>-<+>---<

Saída

+++>-<+>---<

Você pode aceitar entrada e saída como desejar - stdin / stdout, uma função etc., mas a entrada pode não ser codificada.

Isso é , então o código mais curto na contagem de caracteres vencerá.

Maçaneta da porta
fonte
4
Sei que esse é um desafio antigo, mas os casos de teste são inadequados. ++>>++<<--deve sair >>++<<, e isso não foi coberto. Por favor, adicione mais casos de teste.
mbomb007
@ mbomb007 você examinou o último caso de teste +++>-<+>---<? Ele pode ser reduzido para evitar movimentos desnecessários do ponteiro, mas a saída esperada o mantém inalterado. Meu entendimento, baseado em olhar tanto para a pergunta quanto para as respostas, é que a maçaneta da porta é legal com a especificação sendo tomada livremente; devemos eliminar quaisquer +-><sequências contíguas no-op , conforme explicitamente declaradas, e além disso é permitido realizar minificação extra como no seu exemplo ++>>++<<--, e também podemos fazer rearranjos, desde que não alterem a funcionalidade do código, por exemplo, >+<+em +>+<.
Mitch Schwartz
@MitchSchwartz "Remova as seqüências dos caracteres + -> <se eles não fizerem nada. Por exemplo, você deve remover +>-<->+<. (Este pode ser o mais difícil e difícil de implementar.) Verifique se você não obteve nenhum falso positivo, como +>-<+>-<, por exemplo, que não deve ser removido ". - isso é meio vago #
mbomb007 26/10
@ mbomb007 E os segundo e terceiro pontos de marcador são redundantes e desnecessários porque estão incluídos no quarto ponto de marcador. E daí? É uma tarefa legal. Meu comentário foi feito para ser construtivo e fornecer esclarecimentos, não para atacá-lo. Por favor, aceite da maneira que pretendi ou me diga como eu deveria ter dito de maneira diferente. Porque você realmente não abordou o que eu escrevi; parece que você está tentando se defender sem ser realmente construtivo. De que maneira você acha isso vago? Como você reescreveu? Deseja editar a pergunta? Deseja perguntar à Maçaneta da porta?
Mitch Schwartz
1
Ah, então só precisamos remover seqüências contíguas?
mbomb007

Respostas:

10

REBEL - 104

_/^_$/$</([^][<>.,+-]|\+-|-\+|<>|><)//((?<X>(<|>))+[+-]+(?!\2)(?<-X><|>)+(?(X)(?!)))([+-]+)/$3$1/.+/$>$&

Uso:

Entrada: Lê uma linha de stdin.

Saída: imprime uma linha no stdout.

Anomalias *:

  • A inserção _faz com que outra linha seja lida e usada, em vez de não produzir nada.
  • O segundo teste é emitido em ++++>----<vez de +++>-<+>---<. Mas tudo bem, certo? ;)
  • >-<+etc. são substituídos por +>-<etc.

Spoiler:

A implementação da anomalia nº 3 torna as coisas bastante triviais.

* Isto não é um erro, é um recurso!

Kendall Frey
fonte
"não é um bug, é um recurso" +1!
Rohan Jhunjhunwala
36

Brainfuck, 579 bytes

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

Com formatação e alguns comentários:

,
[
  <<+>> >>+<<
  [
    [<+> >+<-]
    ++++++[>-------<-]
    >-
    [
      not plus
      -
      [
        not comma
        -
        [
          not minus
          -
          [
            not period
            --------------
            [
              not less than
              --
              [
                not greater than
                <+++++[>------<-]>+
                [
                  not open bracket
                  --
                  [
                    not close bracket
                    <<[-]>>-
                  ]
                ]
                <
              ]
              >
              [
                greater than
                >>-<<
                <<<[-]<[<]<<<[<]
                >>>>>>>>[<]
                <-[+>]
                +[->+]
                >>>>+>[<-]
                <[>+<-<]
                >
              ]
              <
            ]
            >
            [
              less than
              <<<[-]-[<]
              >>>> >>>>>>>[<]
              <<<<<<[<]
              <-[+>]
              +[-<+]
              <<<+<[>-<<<]
              >[-<+<]
            ]
          ]
          <
        ]
        >
        [
          minus
          +>[-<]
          <[<<]
          <[-]>>
        ]
      ]
      <
    ]
    +>
    [
      plus
      -[<-]
      <[>+>+<<-<]
      <[-]>+>
    ]
    <<
    [
      comma or period or bracket
      >-
    ]
    >[,>]
    <
  ]
  comma or period or bracket or eof
  <+<
  [
    start and end same cell
    >
  ]
  >
  [
    >>>
    [
      <<<<[-<]<<<
    ]
    >>>+>>>>
    [
      start right of end
      <<<<->>>>
      [>>>[-<]>>>>]
    ]
  ]
  >
  [
    <<<
    [
      <+[-->>]
    ]
    >[-[.[-]]]
    >[<]
    >
    [
      <<++++++[>+++++++<-]>+>>
      [<<.>>-]
      <<++>-[<.>-]
      +++[<+++++>-]
      +<<<<< <+>
      [
        <<
        [
          go left
          >->>>>>.
          [[-]<<<<]
          <<<+>>>
        ]
        >
        [
          toggle left right
          ->->>>>[-]
        ]
      ]
      <
      [
        toggle right left
        ->+[>>>>>]>>[<]
        <<<<<<<<
        [
          [-]<
        ]
        >
        [
          go right
          ++.[-]
          >>>>>>>
        ]
        <
      ]
    ]
    >>
  ]
  <[>>>>>>>]
  +[-<<<<<[-]<<]
  ,
]

Isso usa a mesma abordagem da solução de Keith Randall, minimizando todas as seqüências contíguas de maneira +-<>ideal por simulação. Por exemplo, +++>-<+>---<torna ++++>----<- >+<+<<+>+<->>>>se e torna - se +<+>>+>.

Experimente online. (Se o valor absoluto de uma célula simulada chegar perto de 256, haverá problemas de estouro.)

A estrutura geral é

while not EOF:
  while not EOF and next char not in ",.[]":
    process char
  print minified sequence (followed by the char in ",.[]" if applicable)

A fita é dividida em nós de 7 células; no início do loop interno, o layout da memória é

0 s 0 c 0 a b

onde sé um sinalizador booleano para a célula inicial, cé o caractere atual, aé a parte negativa do valor da célula simulada (mais um) e bé a parte positiva do valor da célula simulada.

Quando a sequência minificada está sendo impressa, o layout da memória é

d n e 0 0 a b

onde dé um sinalizador booleano para a direção ae bé como antes (mas se torna um / zero quando impresso) ne eé apenas diferente de zero para o nó final; nestá relacionado a quantas vezes o nó foi visto e eé o valor do caractere que interrompeu o loop interno (mais um).

Originalmente, considerei acompanhar mais informações por nó: nó mais à esquerda e mais à direita como sinalizadores booleanos e posição do nó em relação aos nós inicial e final. Mas podemos evitar isso observando as células vizinhas quando necessário e fazendo verificações à esquerda e à direita para encontrar o nó inicial.

Ao imprimir a sequência reduzida e decidir como mover o ponteiro simulado, podemos adotar uma abordagem geral: comece afastando-se do nó final (em uma direção arbitrária se os nós inicial e final forem iguais), vire à esquerda e à direita nós e pare com base no número de vezes que o nó final foi visto: 3 vezes se os nós inicial e final forem os mesmos; caso contrário, 2.

Mitch Schwartz
fonte
2
Fonte: brainfuck. Alvo: cérebro. +1
Erik the Outgolfer
2
Isso cumpre uma recompensa por tempo indeterminado
Destructible Lemon
1
Vou deixar isso atrair alguma atenção e atribuir a recompensa em um ou dois dias
lirtosiast
1
@MitchSchwartz Por acaso você testou seu código? Você pode realmente reduzi-lo! #meta
WallyWest
1
@WallyWest (Isso parece economizar 7 bytes!) Deixa pra lá, o código no link permanente tem quebras de linha.
Dennis
7

Python, 404 caracteres

Este código faz uma otimização perfeita de todas as subsequências de +-<>. Um pouco mais do que você pediu, mas lá está.

M=lambda n:'+'*n+'-'*-n                                                           
def S(b):                                                                         
 s=p=0;t=[0];G,L='><'                                                             
 for c in b:                                                                      
  if'+'==c:t[p]+=1                                                                
  if'-'==c:t[p]-=1                                                                
  if G==c:p+=1;t+=[0]                                                             
  if L==c:s+=1;t=[0]+t                                                            
 if p<s:k=len(t)-1;t,p,s,G,L=t[::-1],k-p,k-s,L,G                                  
 r=[i for i,n in enumerate(t)if n]+[s,p];a,b=min(r),max(r);return(s-a)*L+''.join(M(n)+G for n in t[a:b])+M(t[b])+(b-p)*L                                           
s=b=''                                                                            
for c in raw_input():                                                             
 if c in'[].,':s+=S(b)+c;b=''                                                     
 else:b+=c                                                                        
print s+S(b) 

Funciona simulando as +-<>operações na fita t. sé a posição inicial na fita e pé a posição atual. Após a simulação, ele calcula a extensão [a,b]que precisa ser operada e faz todo o +/- em uma passagem ideal.

Keith Randall
fonte
1

CoffeeScript - 403 397

i=prompt().replace /[^\]\[,.+-><]/g,''
x=(c)->
 t={};p=n=0
 for d in c
  t[p]?=0;switch d
   when'+'then n=1;t[p]++;when'-'then n=1;t[p]--;when'<'then p--;when'>'then p++
 (n=0if v!=0)for k,v of t;n
s=e=0;((e++;(i=(i.substr 0,s)+i.substr e;e=s=0)if x (i.substr s,e-s).split "")while(i[e]||0)!in['[',']',0];e=++s)while s<=i.length
r=/(\+-|-\+|<>|><|^[<>]$)/g
i=i.replace r,'' while r.test i
alert i

Demonstração (perdoe o uso de bit.ly aqui, todo o URL quebraria a margem)

Versão não compactada (com código de depuração):

console.clear()
input = """Should disappear: ++>>+<+++<->-->-<<->-<
Should disappear: +++>-<--->+<
Should stay: +++>-<+>---<"""

input = input.replace /[^\]\[,.+-><]/g, ''
console.log input

execute = (code) ->
  stack = {}
  item = 0
  console.log code
  nop = false
  for char in code
    switch char
      when '+' then nop = true; stack[item]?=0;stack[item]++
      when '-' then nop = true; stack[item]?=0;stack[item]--
      when '<' then item--
      when '>' then item++
  console.debug stack
  (nop = false if v != 0) for k,v of stack
  nop
start = 0
end = 0

while start <= input.length
 while input.charAt(end) not in [ '[', ']', '' ]
  end++
  if execute (input.substring start, end).split("")
    input = (input.substring 0, start) + input.substring end
    end = start = 0
    console.log input
 end = ++start
input = input.replace /(\+-|-\+|<>|><|^(<|>)$)/g, '' while /(\+-|-\+|<>|><)/.test input
console.log 'Result: ' + input
TimWolla
fonte
Uma maneira alternativa de postar demos do Coffeescript é usar o JSFiddle . Na margem esquerda, há um painel de configuração "Idiomas" que permite usar o CoffeeScript em vez de JS.
Peter Taylor
@PeterTaylor Obrigado, eu sabia sobre o JSFiddle antes, mas não que ele possa usar o CoffeeScript
TimWolla
Isso falha >+.-<, produzindo a cadeia vazia em vez de deixá-la inalterada.
Mitch Schwartz