Мінімізуйте 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 І другий і третій точки кулі є зайвими і непотрібними, оскільки вони включені до четвертої точки кулі. І що? Це класне завдання. Мій коментар мав бути конструктивним і давати роз’яснення, а не нападати на вас. Будь ласка, прийміть так, як я задумав, або скажіть, як я мав би сказати це інакше. Тому що ти не дуже звертався до того, що я написав; просто здається, що ти намагаєшся захистити себе, не будучи справді конструктивним. Яким чином ви вважаєте це невиразним? Як би ви це переписали? Ви хочете відредагувати питання? Ви хочете запитати Дверного ручка?
Мітч Шварц

1
О, значить, нам залишається лише видаляти суміжні послідовності?
mbomb007

Відповіді:


10

РЕБЕЛЬ - 104

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

Використання:

Введення: читає один рядок від stdin.

Вихід: друкує один рядок до stdout.

Аномалії *:

  • Введення _призводить до зчитування та використання іншого рядка, а не виведення нічого.
  • Другий тест виходить ++++>----<замість +++>-<+>---<. Але це нормально, правда? ;)
  • >-<+п. замінюються +>-<тощо.

Спойлер:

Реалізація аномалії №3 робить речі досить тривіальними.

* Це не помилка, це особливість!


"це не помилка, її функція" +1!
Rohan Jhunjhunwala

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є значенням char, який зупинив внутрішній цикл (плюс один).

Спочатку я розглядав можливість відстеження додаткової інформації на вузол: крайній лівий і правий вузол як булеві прапори та положення вузла стосовно початкових та кінцевих вузлів. Але ми можемо цього уникнути, переглянувши сусідні комірки, коли це потрібно, і зробивши лівий і правий сканування, щоб знайти початковий вузол.

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


2
Джерело: brainfuck. Мета: мозковий ебать. +1
Ерік Аутгольфер


1
Я дозволю цьому привернути деяку увагу та нагородити
щедроту

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

Альтернативний спосіб розміщення демонстрацій Coffeescript - це використання JSFiddle . У лівому полі знаходиться конфігураційна панель "Мови", яка дозволяє використовувати CoffeeScript замість JS.
Пітер Тейлор

@PeterTaylor Спасибі, я знав про JSFiddle раніше, але не те, що він може використовувати CoffeeScript
TimWolla

Це не вмикається >+.-<, створюючи порожній рядок, а не залишаючи його незмінним.
Мітч Шварц
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.