Minify Brainfuck

22

Su desafío es minimizar el código Brainfuck , de acuerdo con estas reglas:

  • Elimina todo lo que no sea uno de +-><[].,.
  • Para cualquier grupo de consecutiva +o -caracteres, si la cantidad de +s y -s es la misma, eliminarlos.
  • Haga lo mismo que arriba, pero con >y <.
  • Elimina las secuencias de los +-><personajes si no hacen nada. Por ejemplo, debes eliminar +>-<->+<. (Este puede ser el más complicado y difícil de implementar). Asegúrese de no obtener ningún falso positivo, como +>-<+>-<, que no debe eliminarse.

Casos de prueba:

Entrada

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

Salida

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

Entrada

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

Salida

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

Puede aceptar la entrada y salida de la manera que desee: stdin / stdout, una función, etc., pero la entrada puede no estar codificada.

Este es el , por lo que el código más corto en el recuento de personajes ganará.

Pomo de la puerta
fuente
44
Sé que este es un viejo desafío, pero los casos de prueba son inadecuados. ++>>++<<--debería salir >>++<<, y eso no estaba cubierto. Por favor agregue más casos de prueba.
mbomb007
@ mbomb007 ¿examinó el último caso de prueba +++>-<+>---<? Se puede acortar para evitar movimientos innecesarios del puntero, pero el resultado esperado lo deja sin cambios. Mi comprensión basada en mirar tanto la pregunta como las respuestas es que Doorknob es genial con la especificación tomada libremente; debemos eliminar cualquier +-><secuencia contigua no operativa como se indica explícitamente, y más allá de eso, es permisible hacer minificaciones adicionales como en su ejemplo ++>>++<<--, y también podemos hacer reorganizaciones siempre que no cambien la funcionalidad del código, por ejemplo, >+<+en +>+<.
Mitch Schwartz
@MitchSchwartz "Elimina las secuencias de los caracteres + -> <si no hacen nada. Por ejemplo, debes eliminar +>-<->+<. (Este puede ser el más complicado y difícil de implementar). Asegúrate de no obtener ningún falso positivo, como +>-<+>-<, que no debe eliminarse ". - esto es un poco vago
mbomb007
@ mbomb007 Y el segundo y el tercer punto son redundantes e innecesarios porque están incluidos en el cuarto punto. ¿Y qué? Es una tarea genial. Mi comentario estaba destinado a ser constructivo y proporcionar aclaraciones, no para atacarte. Tómelo como pretendía, o dígame cómo debería haberlo dicho de manera diferente. Porque realmente no abordaste lo que escribí; solo parece que estás tratando de defenderte sin ser realmente constructivo. ¿De qué manera lo encuentras vago? ¿Cómo lo reescribirías? ¿Quieres editar la pregunta? ¿Quieres preguntar Doorknob?
Mitch Schwartz
1
Ah, ¿entonces solo tenemos que eliminar secuencias contiguas?
mbomb007

Respuestas:

10

REBELDE - 104

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

Uso:

Entrada: Lee una línea de stdin.

Salida: Imprime una línea en stdout.

Anomalías *:

  • Al ingresar, _se lee y usa otra línea, en lugar de no mostrar nada.
  • La segunda prueba sale en ++++>----<lugar de +++>-<+>---<. Pero eso está bien, ¿verdad? ;)
  • >-<+etc.son reemplazados por +>-<etc.

Spoiler

La implementación de la anomalía # 3 hace que las cosas sean bastante triviales.

* ¡No es un error, es una característica!

Kendall Frey
fuente
"no es un error, es una característica" +1!
Rohan Jhunjhunwala
36

Brainfuck, 579 bytes

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

Con formato y algunos comentarios:

,
[
  <<+>> >>+<<
  [
    [<+> >+<-]
    ++++++[>-------<-]
    >-
    [
      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
          ++.[-]
          >>>>>>>
        ]
        <
      ]
    ]
    >>
  ]
  <[>>>>>>>]
  +[-<<<<<[-]<<]
  ,
]

Utiliza el mismo enfoque que la solución de Keith Randall, minimizando todas las secuencias contiguas de +-<>manera óptima mediante simulación. Por ejemplo, se +++>-<+>---<vuelve ++++>----<y se >+<+<<+>+<->>>>vuelve +<+>>+>.

Pruébalo en línea. (Si el valor absoluto de una celda simulada se acerca a 256, habrá problemas de desbordamiento).

La estructura general es

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

La cinta se divide en nodos de 7 celdas; al comienzo del bucle interno, el diseño de la memoria es

0 s 0 c 0 a b

donde ses un indicador booleano para la celda de inicio, ces el carácter actual, aes la parte negativa del valor de la celda simulada (más uno) y bes la parte positiva del valor de la celda simulada.

Cuando se imprime la secuencia minimizada, el diseño de la memoria es

d n e 0 0 a b

donde des una bandera booleana para la dirección, ay bson como antes (pero se convierten en uno / cero cuando se imprimen), ny no eson cero para el nodo final; nestá relacionado con cuántas veces se ha visto el nodo y ees el valor del carácter que detuvo el bucle interno (más uno).

Originalmente consideré realizar un seguimiento de más información por nodo: nodo más a la izquierda y más a la derecha como banderas booleanas, y la posición del nodo en relación con los nodos de inicio y fin. Pero podemos evitar eso mirando las celdas vecinas cuando sea necesario, y haciendo escaneos izquierdo y derecho para encontrar el nodo de inicio.

Al imprimir la secuencia minimizada y decidir cómo mover el puntero simulado, podemos adoptar un enfoque general: comience alejándose del nodo final (en una dirección arbitraria si los nodos de inicio y final son los mismos), gire a la izquierda y a la derecha nodos, y se detiene en función del número de veces que se ha visto el nodo final: 3 veces si los nodos de inicio y final son iguales, de lo contrario 2.

Mitch Schwartz
fuente
2
Fuente: brainfuck. Objetivo: brainfuck. +1
Erik the Outgolfer
2
Esto cumple una recompensa indefinida
Destructible Lemon
1
Dejaré que esto atraiga algo de atención y otorgue la recompensa en un día o dos
lirtosiast el
1
@MitchSchwartz ¿Por casualidad probaste tu código contra tu código? ¡En realidad puedes acortarlo! #meta
WallyWest
1
@WallyWest (¡Eso parece ahorrar 7 bytes!) No importa, el código en el enlace permanente tiene saltos de línea.
Dennis
7

Python, 404 caracteres

Este código hace una optimización perfecta de todas las subsecuencias de +-<> . Un poco más de lo que pediste, pero ahí lo tienes.

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 las +-<>operaciones en la cinta t. ses la posición inicial en la cinta y pes la posición actual. Después de la simulación, calcula la extensión[a,b] que debe operarse y realiza todos los +/- en una pasada óptima.

Keith Randall
fuente
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

Manifestación (por favor, perdone el uso de bit.ly aquí, toda la URL rompería el descuento)

Versión sin comprimir (con código de depuración):

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
fuente
Una forma alternativa de publicar demostraciones de Coffeescript es usar JSFiddle . En el margen izquierdo hay un panel de configuración "Idiomas" que le permite usar CoffeeScript en lugar de JS.
Peter Taylor
@PeterTaylor Gracias, sabía sobre JSFiddle antes, pero no es que sea capaz de usar CoffeeScript
TimWolla el
Esto falla al >+.-<producir la cadena vacía en lugar de dejarla sin cambios.
Mitch Schwartz el