Minify Brainfuck

22

Ваша задача - минимизировать код Brainfuck в соответствии с этими правилами:

  • Удалите все, что не является одним из +-><[].,.
  • Для любой группы подряд +или -символов, если сумма+ s и -s одинаково, удалите их.
  • Сделайте то же, что и выше, но с >и< .
  • Удалить последовательности +-><символов, если они ничего не делают. Например, вы должны удалить +>-<->+<. (Это может быть самым сложным и сложным для реализации.) Убедитесь, что вы не получите никаких ложных срабатываний, например +>-<+>-<, которые не должны быть удалены.

Тестовые случаи:

вход

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

Выход

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

вход

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

Выход

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

Вы можете принимать ввод и вывод, как вам угодно - stdin / stdout, функция и т. Д., Но ввод может быть не закодирован.

Это , поэтому победит самый короткий код в количестве символов.

Дверная ручка
источник
4
Я знаю, что это старая проблема, но контрольные примеры неадекватны. ++>>++<<--должен выводить >>++<<, и это не было покрыто. Пожалуйста, добавьте больше тестовых случаев.
mbomb007
@ mbomb007 ты проверял последний контрольный пример +++>-<+>---<? Его можно сократить, чтобы избежать ненужного перемещения указателя, но ожидаемый результат оставляет его неизменным. Мое понимание, основанное на рассмотрении как вопроса, так и ответов, заключается в том, что дверная ручка хороша, если спецификация принимается свободно; мы должны исключить любые непрерывные неактивные +-><последовательности, как указано явным образом, кроме того, разрешено выполнять дополнительное минимизацию, как в вашем примере ++>>++<<--, и мы также можем выполнять перестановки, если они не изменяют функциональность кода, например, >+<+в +>+<,
Митч Шварц
@MitchSchwartz "Удаляйте последовательности символов + -> <, если они ничего не делают. Например, вы должны удалить +>-<->+<. (Это может быть самым сложным и сложным для реализации.) Убедитесь, что вы не получаете ложных срабатываний, например +>-<+>-<, который не должен быть удален ". - это немного расплывчато
mbomb007
@ mbomb007 А вторая и третья маркированные точки являются избыточными и ненужными, поскольку они включены в четвертую маркированную точку. Ну и что? Это классная задача. Мой комментарий должен был быть конструктивным и давать разъяснения, а не нападать на вас. Пожалуйста, примите это так, как я хотел, или скажите, как я должен был сказать это иначе. Потому что вы на самом деле не обратились к тому, что я написал; просто кажется, что ты пытаешься защитить себя, не будучи действительно конструктивным. Каким образом вы находите это расплывчатым? Как бы вы переписали это? Хотите отредактировать вопрос? Хотите спросить ручку двери?
Митч Шварц
1
О, так что мы должны только удалить смежные последовательности?
mbomb007

Ответы:

10

REBEL - 104

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

Использование:

Ввод: читает одну строку из стандартного ввода.

Вывод: печатает одну строку в стандартный вывод.

Аномалии *:

  • Ввод _приводит к прочтению и использованию другой строки, а не к выводу ничего.
  • Второй тест выводит ++++>----<вместо +++>-<+>---<. Но это нормально, верно? ;)
  • >-<+и т. д. заменены на +>-<и т. д.

Спойлер:

Реализация аномалии № 3 делает вещи довольно тривиальными.

* Это не ошибка, это особенность!

Кендалл Фрей
источник
"это не ошибка, это особенность" +1!
Рохан Джунджхунвала
36

Brainfuck, 579 байтов

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

С форматированием и некоторыми комментариями:

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

Это использует тот же подход, что и решение Кейта Рэндалла, минимизируя все смежные последовательности +-<>оптимально путем симуляции. Например, +++>-<+>---<становится ++++>----<и >+<+<<+>+<->>>>становится+<+>>+> .

Попробуйте онлайн. (Если абсолютное значение моделируемой ячейки приближается к 256, возникнут проблемы переполнения.)

Общая структура

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

Лента разделена на 7-элементные узлы; в начале внутреннего цикла макет памяти

0 s 0 c 0 a b

где s- логический флаг для начальной ячейки, cтекущий символ, aотрицательная часть значения моделируемой ячейки (плюс один), иb положительная часть имитируемого значения ячейки.

Когда минимизированная последовательность печатается, макет памяти

d n e 0 0 a b

где dэто логический флаг для направления, aи bэто , как и раньше (но становится одним / ноля при печати), а также nи eтолько отлична от нуля для конечного узла; nсвязано с тем, сколько раз узел был замечен, иe является значением символа, который остановил внутренний цикл (плюс один).

Первоначально я рассматривал отслеживание большего количества информации на узел: самый левый и самый правый узел в виде логических флагов, а также положение узла по отношению к начальному и конечному узлам. Но мы можем избежать этого, просматривая соседние ячейки, когда это необходимо, и сканируя влево и вправо, чтобы найти начальный узел.

При печати минимизированной последовательности и принятии решения о том, как перемещать симулируемый указатель, мы можем выбрать общий подход: начать с удаления от конечного узла (в произвольном направлении, если начальный и конечный узлы совпадают), развернуться в крайнем левом и правом краях узлы и остановка в зависимости от того, сколько раз был замечен конечный узел: 3 раза, если начальный и конечный узлы совпадают, в противном случае 2.

Митч Шварц
источник
2
Источник: Brainfuck. Цель: мозговой трах. +1
Эрик Outgolfer
2
Это выполняет неопределенное вознаграждение
Разрушаемый Лимон
1
Я позволю этому привлечь некоторое внимание и наградить награду через день или два
lirtosiast
1
@MitchSchwartz Вы проверяли свой код на соответствие вашему коду? Вы можете сократить его! #meta
WallyWest
1
@WallyWest (это, кажется, экономит 7 байт!) Не имеет значения, код в постоянной ссылке имеет разрывы строк.
Деннис
7

Питон, 404 символа

Этот код делает идеальную оптимизацию всех подпоследовательностей +-<>. Чуть больше, чем вы просили, но вы идете.

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) 

Он работает путем имитации +-<>операций на ленте t. sэто начальная позиция на ленте и pтекущая позиция. После моделирования он вычисляет степень, с [a,b]которой необходимо работать, и выполняет все +/- за один оптимальный проход.

Кит Рэндалл
источник
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

Демо (пожалуйста, прости использование bit.ly здесь, весь URL сломал бы уценку)

Несжатая версия (с отладочным кодом):

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
источник
Альтернативный способ размещения демоверсий Coffeescript - использование JSFiddle . В левом поле находится панель конфигурации «Языки», которая позволяет использовать CoffeeScript вместо JS.
Питер Тейлор
@PeterTaylor Спасибо, я знал о JSFiddle раньше, но не то, чтобы он мог использовать CoffeeScript
TimWolla
Это терпит неудачу >+.-<, производя пустую строку вместо того, чтобы оставить это неизменным.
Митч Шварц