Minify Brainfuck


22

Votre défi est de minimiser le code Brainfuck , selon ces règles:

  • Retirez tout ce qui n'en fait pas partie +-><[].,.
  • Pour tout groupe de caractères consécutifs +ou -, si le nombre de +s et de -s est le même, supprimez-les.
  • Faites de même que ci-dessus, mais avec >et <.
  • Supprimez les séquences des +-><personnages s'ils ne font rien. Par exemple, vous devez supprimer +>-<->+<. (Cela peut être le plus délicat et le plus difficile à implémenter.) Assurez-vous que vous n'obtenez aucun faux positif, comme +>-<+>-<, qui ne devrait pas être supprimé.

Cas de test:

Contribution

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

Sortie

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

Contribution

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

Sortie

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

Vous pouvez accepter l'entrée et la sortie comme vous le souhaitez - stdin / stdout, une fonction, etc., mais l'entrée peut ne pas être codée en dur.

C'est le , donc le code le plus court en nombre de caractères gagnera.


4
Je sais que c'est un vieux défi, mais les cas de test sont inadéquats. ++>>++<<--devrait sortir >>++<<, et cela n'a pas été couvert. Veuillez ajouter d'autres cas de test.
mbomb007

@ mbomb007 avez - vous examiné le dernier cas de test, +++>-<+>---<? Il peut être raccourci pour éviter un mouvement inutile du pointeur, mais la sortie attendue ne le modifie pas. Ma compréhension basée sur l'examen à la fois de la question et des réponses est que la poignée de porte est cool avec les spécifications prises de manière lâche; nous devons éliminer toutes les +-><séquences contiguës sans opération comme indiqué explicitement, et au-delà, il est autorisé de faire une minification supplémentaire comme dans votre exemple ++>>++<<--, et nous pouvons également effectuer des réarrangements tant qu'ils ne modifient pas la fonctionnalité du code, par exemple >+<+en +>+<.
Mitch Schwartz

@MitchSchwartz "Supprimez les séquences des caractères + -> <s'ils ne font rien. Par exemple, vous devez les supprimer +>-<->+<. (Cela peut être le plus délicat et le plus difficile à implémenter.) Assurez-vous de ne pas obtenir de faux positifs, comme +>-<+>-<, qui ne devraient pas être supprimés. " - c'est un peu vague
mbomb007

@ mbomb007 Et les deuxième et troisième puces sont redondantes et inutiles car elles sont incluses dans la quatrième puce. Et alors? C'est une tâche cool. Mon commentaire était censé être constructif et apporter des éclaircissements, pas pour vous attaquer. Veuillez le prendre comme je l’aurais voulu ou dites-moi comment j'aurais dû le dire différemment. Parce que vous n'avez pas vraiment abordé ce que j'ai écrit; on dirait juste que vous essayez de vous défendre sans être vraiment constructif. En quoi le trouvez-vous vague? Comment le réécririez-vous? Voulez-vous modifier la question? Voulez-vous demander Doorknob?
Mitch Schwartz

1
Oh, nous n'avons donc qu'à supprimer les séquences contiguës?
mbomb007

Réponses:


10

REBEL - 104

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

Usage:

Entrée: lit une ligne depuis stdin.

Sortie: imprime une ligne vers la sortie standard.

Anomalies *:

  • La saisie _entraîne la lecture et l'utilisation d'une autre ligne, plutôt que la sortie de rien.
  • Le deuxième test sort ++++>----<au lieu de +++>-<+>---<. Mais c'est OK, non? ;)
  • >-<+etc. sont remplacés par +>-<etc.

Becquet:

L'implémentation de l'anomalie # 3 rend les choses assez triviales.

* Ce n'est pas un bug, c'est une fonctionnalité!


"ce n'est pas un bug c'est une fonctionnalité" +1!
Rohan Jhunjhunwala

36

Brainfuck, 579 octets

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

Avec mise en forme et quelques commentaires:

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

Cela utilise la même approche que la solution de Keith Randall, en minimisant toutes les séquences contiguës de +-<>manière optimale par simulation. Par exemple,+++>-<+>---< devient ++++>----<et >+<+<<+>+<->>>>devient +<+>>+>.

Essayez-le en ligne. (Si la valeur absolue d'une cellule simulée devient proche de 256, il y aura des problèmes de débordement.)

La structure globale est

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

La bande est divisée en nœuds à 7 cellules; au début de la boucle interne, la disposition de la mémoire est

0 s 0 c 0 a b

sest un drapeau booléen pour la cellule de départ,c est le caractère actuel, aest la partie négative de la valeur de cellule simulée (plus un) et best la partie positive de la valeur de cellule simulée.

Lorsque la séquence réduite est imprimée, la disposition de la mémoire est

d n e 0 0 a b

dest un drapeau booléen pour la direction, aet bsont comme avant (mais deviennent un / zéro lors de l'impression), et net ene sont pas différents de zéro pour le nœud final;nest lié au nombre de fois où le nœud a été vu, et eest la valeur du caractère qui a interrompu la boucle interne (plus un).

À l'origine, j'ai envisagé de conserver plus d'informations par nœud: le nœud le plus à gauche et le plus à droite en tant que drapeaux booléens, et la position du nœud par rapport aux nœuds de début et de fin. Mais nous pouvons éviter cela en regardant les cellules voisines lorsque cela est nécessaire, et en effectuant des analyses à gauche et à droite afin de trouver le nœud de départ.

Lorsque vous imprimez la séquence réduite et décidez comment déplacer le pointeur simulé, nous pouvons adopter une approche générale: commencer par s'éloigner du nœud final (dans une direction arbitraire si les nœuds de début et de fin sont identiques), faire demi-tour à gauche et à droite nœuds et s'arrête en fonction du nombre de fois où le nœud final a été vu: 3 fois si les nœuds de début et de fin sont identiques, sinon 2.


2
Source: brainfuck. Cible: brainfuck. +1
Erik l'Outgolfer

2

1
Je vais laisser cela attirer l'attention et attribuer la prime dans un jour ou deux
lirtosiast

1
@MitchSchwartz Avez-vous testé votre code par rapport à votre code? Vous pouvez même le raccourcir! #meta
WallyWest

1
@WallyWest (Cela semble économiser 7 octets!) Peu importe, le code dans le permalien a des sauts de ligne.
Dennis

7

Python, 404 caractères

Ce code optimise parfaitement toutes les sous-séquences de +-<>. Un peu plus que ce que vous aviez demandé, mais voilà.

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) 

Il fonctionne en simulant les +-<>opérations sur la bande t. sest la position de départ sur la bande et pla position actuelle. Après la simulation, il détermine l'étendue [a,b]à opérer et effectue tous les +/- en un seul passage optimal.


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

Démo (veuillez pardonner l'utilisation de bit.ly ici, l'URL entière casserait la démarque)

Version non compressée (avec code de débogage):

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

Une autre façon de publier des démos Coffeescript est d'utiliser JSFiddle . Dans la marge de gauche, il y a un volet de configuration "Langues" qui vous permet d'utiliser CoffeeScript au lieu de JS.
Peter Taylor

@PeterTaylor Merci, je connaissais JSFiddle avant, mais pas qu'il soit capable d'utiliser CoffeeScript
TimWolla

Cela échoue >+.-<, produisant la chaîne vide au lieu de la laisser inchangée.
Mitch Schwartz
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.